Skip to main content

PiecewiseLinearTransfer

Struct PiecewiseLinearTransfer 

Source
pub struct PiecewiseLinearTransfer<const N: usize> { /* private fields */ }
Expand description

A sparse, nonuniform, piecewise-linear u16 to i32 transfer function.

Inputs are searched in O(log N) time. The two arrays use six bytes of table payload per knot and require no allocation. Inverse conversion binary-searches the same output knots — no dense physical→input LUT.

An optional ObservationGuard is stored on the table itself. A transfer constructed without one keeps the previous convert/invert behavior; its layout may grow by that optional field. Exact size_of is target/ABI-dependent.

Implementations§

Source§

impl<const N: usize> PiecewiseLinearTransfer<N>

Source

pub const fn new( inputs: &'static [u16; N], outputs: &'static [i32; N], direction: MonotonicDirection, ) -> Self

Construct a transfer whose below/above behaviors both default to error.

Flat runs default to FlatResolution::PreferLowInput.

§Panics

Panics while defining the table if it has fewer than two knots, inputs are not strictly increasing, or outputs violate direction. Generated tables call this in a constant context, making invalid tables a compile error. Conversion of caller-supplied observations does not panic.

Examples found in repository?
examples/../tests/fixtures/ntc_generated.rs (line 22)
21pub const NTC_10K_BETA_3950: PiecewiseLinearTransfer<61> =
22PiecewiseLinearTransfer::new(&NTC_10K_BETA_3950_INPUTS, &NTC_10K_BETA_3950_OUTPUTS, MonotonicDirection::Decreasing)
23.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Error);
More examples
Hide additional examples
examples/../tests/fixtures/observation_guards_generated.rs (line 23)
22pub const GUARDED_ERROR: PiecewiseLinearTransfer<2> =
23PiecewiseLinearTransfer::new(&GUARDED_ERROR_INPUTS, &GUARDED_ERROR_OUTPUTS, MonotonicDirection::Increasing)
24.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
25.with_observation_guard(65535, ObservationGuardBehavior::Error);
26/// Metadata for [`GUARDED_ERROR`].
27pub const GUARDED_ERROR_METADATA: TransferMetadata = TransferMetadata {
28    input_unit: "count",
29    output_unit: "unit",
30    output_scale: 1,
31    domain_min: 1,
32    domain_max: 10,
33    range_min: 1,
34    range_max: 10,
35    direction: MonotonicDirection::Increasing,
36    knot_count: 2,
37    strictly_monotonic: true,
38    flat_segment_count: 0,
39    requested_max_error: 1,
40    achieved_max_error: 0,
41    worst_case_input: 1,
42    achieved_max_inverse_code_error: 0,
43};
44/// Optional observation-code guard for [`GUARDED_ERROR`].
45///
46/// Classification of a code as saturation is declared consumer/device policy,
47/// not inferred from the integer value. The runtime getter and this constant agree.
48pub const GUARDED_ERROR_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
49    code: 65535,
50    behavior: ObservationGuardBehavior::Error,
51});
52
53#[rustfmt::skip]
54static GUARDED_FAMILY_VARIANT_CLAMP_INPUTS: [u16; 2] = [1, 10];
55#[rustfmt::skip]
56static GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS: [i32; 2] = [10, 1];
57/// Family: "guarded\_family".
58/// Selectors: "variant" = "clamp".
59/// "guarded\_family\_variant\_clamp" sparse physical transfer function.
60///
61/// Source provenance: identity "test fixture".
62/// Representation: "formula y = 11 - x".
63/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = clamp; above = error.
64/// Domain: 1..=10 "count"; output: "unit" x 1.
65/// Knots: 2 (12 bytes array payload).
66/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
67/// (conservative metadata bound 0) at input 1.
68/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
69/// Observation guard: code 65535 with Clamp behavior.
70/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
71#[rustfmt::skip]
72pub const GUARDED_FAMILY_VARIANT_CLAMP: PiecewiseLinearTransfer<2> =
73PiecewiseLinearTransfer::new(&GUARDED_FAMILY_VARIANT_CLAMP_INPUTS, &GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS, MonotonicDirection::Decreasing)
74.with_boundaries(BoundaryBehavior::Clamp, BoundaryBehavior::Error)
75.with_observation_guard(65535, ObservationGuardBehavior::Clamp);
examples/../tests/fixtures/family_acceptance_generated.rs (line 34)
33pub const FRONT_END_HIGH_DC: PiecewiseLinearTransfer<2> =
34PiecewiseLinearTransfer::new(&FRONT_END_HIGH_DC_INPUTS, &FRONT_END_HIGH_DC_OUTPUTS, MonotonicDirection::Increasing)
35.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
36.with_observation_guard(65535, ObservationGuardBehavior::Error);
37/// Metadata for [`FRONT_END_HIGH_DC`].
38pub const FRONT_END_HIGH_DC_METADATA: TransferMetadata = TransferMetadata {
39    input_unit: "adc_code",
40    output_unit: "millivolt",
41    output_scale: 1000,
42    domain_min: 100,
43    domain_max: 250,
44    range_min: 3201,
45    range_max: 8006,
46    direction: MonotonicDirection::Increasing,
47    knot_count: 2,
48    strictly_monotonic: true,
49    flat_segment_count: 0,
50    requested_max_error: 1,
51    achieved_max_error: 1,
52    worst_case_input: 175,
53    achieved_max_inverse_code_error: 0,
54};
55/// Optional observation-code guard for [`FRONT_END_HIGH_DC`].
56///
57/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
58/// not inferred from the integer value. The runtime getter and this constant agree.
59pub const FRONT_END_HIGH_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
60    code: 65535,
61    behavior: ObservationGuardBehavior::Error,
62});
63
64#[rustfmt::skip]
65static FRONT_END_LOW_DC_INPUTS: [u16; 2] = [100, 500];
66#[rustfmt::skip]
67static FRONT_END_LOW_DC_OUTPUTS: [i32; 2] = [200, 1000];
68/// Family: "front\_end".
69/// Selectors: "coupling" = "dc", "range" = "low".
70/// "front\_end\_low\_dc" sparse physical transfer function.
71///
72/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
73/// Representation: "scaled polynomial (3 coefficients, scale=2000/1000000)".
74/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
75/// Domain: 100..=500 "adc\_code"; output: "millivolt" x 1000.
76/// Knots: 2 (12 bytes array payload).
77/// Exhaustive numerical error: requested <= 1, achieved 0.100000 output quanta
78/// (conservative metadata bound 1) at input 500.
79/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
80/// Observation guard: code 65535 with Error behavior.
81/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
82#[rustfmt::skip]
83pub const FRONT_END_LOW_DC: PiecewiseLinearTransfer<2> =
84PiecewiseLinearTransfer::new(&FRONT_END_LOW_DC_INPUTS, &FRONT_END_LOW_DC_OUTPUTS, MonotonicDirection::Increasing)
85.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
86.with_observation_guard(65535, ObservationGuardBehavior::Error);
87/// Metadata for [`FRONT_END_LOW_DC`].
88pub const FRONT_END_LOW_DC_METADATA: TransferMetadata = TransferMetadata {
89    input_unit: "adc_code",
90    output_unit: "millivolt",
91    output_scale: 1000,
92    domain_min: 100,
93    domain_max: 500,
94    range_min: 200,
95    range_max: 1000,
96    direction: MonotonicDirection::Increasing,
97    knot_count: 2,
98    strictly_monotonic: true,
99    flat_segment_count: 0,
100    requested_max_error: 1,
101    achieved_max_error: 1,
102    worst_case_input: 500,
103    achieved_max_inverse_code_error: 0,
104};
105/// Optional observation-code guard for [`FRONT_END_LOW_DC`].
106///
107/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
108/// not inferred from the integer value. The runtime getter and this constant agree.
109pub const FRONT_END_LOW_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
110    code: 65535,
111    behavior: ObservationGuardBehavior::Error,
112});
113
114#[rustfmt::skip]
115static FRONT_END_MID_DC_INPUTS: [u16; 2] = [100, 400];
116#[rustfmt::skip]
117static FRONT_END_MID_DC_OUTPUTS: [i32; 2] = [800, 3201];
118/// Family: "front\_end".
119/// Selectors: "coupling" = "dc", "range" = "mid".
120/// "front\_end\_mid\_dc" sparse physical transfer function.
121///
122/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
123/// Representation: "scaled polynomial (3 coefficients, scale=8000/1000000)".
124/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
125/// Domain: 100..=400 "adc\_code"; output: "millivolt" x 1000.
126/// Knots: 2 (12 bytes array payload).
127/// Exhaustive numerical error: requested <= 1, achieved 0.600000 output quanta
128/// (conservative metadata bound 1) at input 250.
129/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
130/// Observation guard: code 65535 with Error behavior.
131/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
132#[rustfmt::skip]
133pub const FRONT_END_MID_DC: PiecewiseLinearTransfer<2> =
134PiecewiseLinearTransfer::new(&FRONT_END_MID_DC_INPUTS, &FRONT_END_MID_DC_OUTPUTS, MonotonicDirection::Increasing)
135.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
136.with_observation_guard(65535, ObservationGuardBehavior::Error);
137/// Metadata for [`FRONT_END_MID_DC`].
138pub const FRONT_END_MID_DC_METADATA: TransferMetadata = TransferMetadata {
139    input_unit: "adc_code",
140    output_unit: "millivolt",
141    output_scale: 1000,
142    domain_min: 100,
143    domain_max: 400,
144    range_min: 800,
145    range_max: 3201,
146    direction: MonotonicDirection::Increasing,
147    knot_count: 2,
148    strictly_monotonic: true,
149    flat_segment_count: 0,
150    requested_max_error: 1,
151    achieved_max_error: 1,
152    worst_case_input: 250,
153    achieved_max_inverse_code_error: 0,
154};
155/// Optional observation-code guard for [`FRONT_END_MID_DC`].
156///
157/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
158/// not inferred from the integer value. The runtime getter and this constant agree.
159pub const FRONT_END_MID_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
160    code: 65535,
161    behavior: ObservationGuardBehavior::Error,
162});
163
164#[rustfmt::skip]
165static GUARDED_IDENTITY_INPUTS: [u16; 2] = [1, 10];
166#[rustfmt::skip]
167static GUARDED_IDENTITY_OUTPUTS: [i32; 2] = [1, 10];
168/// "guarded\_identity" sparse physical transfer function.
169///
170/// Source provenance: none declared.
171/// Representation: "formula y = x".
172/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = error; above = clamp.
173/// Domain: 1..=10 "adc\_code"; output: "millivolt" x 1.
174/// Knots: 2 (12 bytes array payload).
175/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
176/// (conservative metadata bound 0) at input 1.
177/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
178/// Observation guard: code 65535 with Error behavior.
179/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
180#[rustfmt::skip]
181pub const GUARDED_IDENTITY: PiecewiseLinearTransfer<2> =
182PiecewiseLinearTransfer::new(&GUARDED_IDENTITY_INPUTS, &GUARDED_IDENTITY_OUTPUTS, MonotonicDirection::Increasing)
183.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
184.with_observation_guard(65535, ObservationGuardBehavior::Error);
examples/no_std_generated_fixtures.rs (lines 24-28)
23pub fn runtime_api_smoke(code: u16, sample: u32) -> (i32, u16, u32, bool) {
24    let transfer = PiecewiseLinearTransfer::new(
25        &SMOKE_INPUTS,
26        &SMOKE_OUTPUTS,
27        MonotonicDirection::Increasing,
28    );
29    let calibrated = match AffineCalibration::new(transfer, 1_001, 0, 1_000) {
30        Ok(value) => value,
31        Err(_) => unreachable!(),
32    };
33    let physical = calibrated.convert(code).unwrap_or_default();
34    let inverse = calibrated.invert(physical).unwrap_or_default();
35
36    let affine = match AffineTransform::new(1_001, 0, 1_000) {
37        Ok(value) => value,
38        Err(_) => unreachable!(),
39    };
40    let _ = affine
41        .apply(physical)
42        .and_then(|value| affine.unapply(value));
43
44    let mut average = MovingAverage::<u32, 1>::new();
45    let filtered = match average.update(sample) {
46        FilterOutput::Ready(value) => value,
47        FilterOutput::WarmingUp { .. } => unreachable!(),
48    };
49    let mut latch = Hysteresis::<u32>::new(100, 200);
50    (physical, inverse, filtered, latch.update(filtered))
51}
Source

pub const fn with_boundaries( self, below: BoundaryBehavior, above: BoundaryBehavior, ) -> Self

Set independent below-domain and above-domain behavior.

Both are declared against the observation domain. Inverse conversion maps them onto the physical range through the table’s direction; see range_behaviors.

Examples found in repository?
examples/../tests/fixtures/ntc_generated.rs (line 23)
21pub const NTC_10K_BETA_3950: PiecewiseLinearTransfer<61> =
22PiecewiseLinearTransfer::new(&NTC_10K_BETA_3950_INPUTS, &NTC_10K_BETA_3950_OUTPUTS, MonotonicDirection::Decreasing)
23.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Error);
More examples
Hide additional examples
examples/../tests/fixtures/observation_guards_generated.rs (line 24)
22pub const GUARDED_ERROR: PiecewiseLinearTransfer<2> =
23PiecewiseLinearTransfer::new(&GUARDED_ERROR_INPUTS, &GUARDED_ERROR_OUTPUTS, MonotonicDirection::Increasing)
24.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
25.with_observation_guard(65535, ObservationGuardBehavior::Error);
26/// Metadata for [`GUARDED_ERROR`].
27pub const GUARDED_ERROR_METADATA: TransferMetadata = TransferMetadata {
28    input_unit: "count",
29    output_unit: "unit",
30    output_scale: 1,
31    domain_min: 1,
32    domain_max: 10,
33    range_min: 1,
34    range_max: 10,
35    direction: MonotonicDirection::Increasing,
36    knot_count: 2,
37    strictly_monotonic: true,
38    flat_segment_count: 0,
39    requested_max_error: 1,
40    achieved_max_error: 0,
41    worst_case_input: 1,
42    achieved_max_inverse_code_error: 0,
43};
44/// Optional observation-code guard for [`GUARDED_ERROR`].
45///
46/// Classification of a code as saturation is declared consumer/device policy,
47/// not inferred from the integer value. The runtime getter and this constant agree.
48pub const GUARDED_ERROR_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
49    code: 65535,
50    behavior: ObservationGuardBehavior::Error,
51});
52
53#[rustfmt::skip]
54static GUARDED_FAMILY_VARIANT_CLAMP_INPUTS: [u16; 2] = [1, 10];
55#[rustfmt::skip]
56static GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS: [i32; 2] = [10, 1];
57/// Family: "guarded\_family".
58/// Selectors: "variant" = "clamp".
59/// "guarded\_family\_variant\_clamp" sparse physical transfer function.
60///
61/// Source provenance: identity "test fixture".
62/// Representation: "formula y = 11 - x".
63/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = clamp; above = error.
64/// Domain: 1..=10 "count"; output: "unit" x 1.
65/// Knots: 2 (12 bytes array payload).
66/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
67/// (conservative metadata bound 0) at input 1.
68/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
69/// Observation guard: code 65535 with Clamp behavior.
70/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
71#[rustfmt::skip]
72pub const GUARDED_FAMILY_VARIANT_CLAMP: PiecewiseLinearTransfer<2> =
73PiecewiseLinearTransfer::new(&GUARDED_FAMILY_VARIANT_CLAMP_INPUTS, &GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS, MonotonicDirection::Decreasing)
74.with_boundaries(BoundaryBehavior::Clamp, BoundaryBehavior::Error)
75.with_observation_guard(65535, ObservationGuardBehavior::Clamp);
examples/../tests/fixtures/family_acceptance_generated.rs (line 35)
33pub const FRONT_END_HIGH_DC: PiecewiseLinearTransfer<2> =
34PiecewiseLinearTransfer::new(&FRONT_END_HIGH_DC_INPUTS, &FRONT_END_HIGH_DC_OUTPUTS, MonotonicDirection::Increasing)
35.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
36.with_observation_guard(65535, ObservationGuardBehavior::Error);
37/// Metadata for [`FRONT_END_HIGH_DC`].
38pub const FRONT_END_HIGH_DC_METADATA: TransferMetadata = TransferMetadata {
39    input_unit: "adc_code",
40    output_unit: "millivolt",
41    output_scale: 1000,
42    domain_min: 100,
43    domain_max: 250,
44    range_min: 3201,
45    range_max: 8006,
46    direction: MonotonicDirection::Increasing,
47    knot_count: 2,
48    strictly_monotonic: true,
49    flat_segment_count: 0,
50    requested_max_error: 1,
51    achieved_max_error: 1,
52    worst_case_input: 175,
53    achieved_max_inverse_code_error: 0,
54};
55/// Optional observation-code guard for [`FRONT_END_HIGH_DC`].
56///
57/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
58/// not inferred from the integer value. The runtime getter and this constant agree.
59pub const FRONT_END_HIGH_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
60    code: 65535,
61    behavior: ObservationGuardBehavior::Error,
62});
63
64#[rustfmt::skip]
65static FRONT_END_LOW_DC_INPUTS: [u16; 2] = [100, 500];
66#[rustfmt::skip]
67static FRONT_END_LOW_DC_OUTPUTS: [i32; 2] = [200, 1000];
68/// Family: "front\_end".
69/// Selectors: "coupling" = "dc", "range" = "low".
70/// "front\_end\_low\_dc" sparse physical transfer function.
71///
72/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
73/// Representation: "scaled polynomial (3 coefficients, scale=2000/1000000)".
74/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
75/// Domain: 100..=500 "adc\_code"; output: "millivolt" x 1000.
76/// Knots: 2 (12 bytes array payload).
77/// Exhaustive numerical error: requested <= 1, achieved 0.100000 output quanta
78/// (conservative metadata bound 1) at input 500.
79/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
80/// Observation guard: code 65535 with Error behavior.
81/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
82#[rustfmt::skip]
83pub const FRONT_END_LOW_DC: PiecewiseLinearTransfer<2> =
84PiecewiseLinearTransfer::new(&FRONT_END_LOW_DC_INPUTS, &FRONT_END_LOW_DC_OUTPUTS, MonotonicDirection::Increasing)
85.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
86.with_observation_guard(65535, ObservationGuardBehavior::Error);
87/// Metadata for [`FRONT_END_LOW_DC`].
88pub const FRONT_END_LOW_DC_METADATA: TransferMetadata = TransferMetadata {
89    input_unit: "adc_code",
90    output_unit: "millivolt",
91    output_scale: 1000,
92    domain_min: 100,
93    domain_max: 500,
94    range_min: 200,
95    range_max: 1000,
96    direction: MonotonicDirection::Increasing,
97    knot_count: 2,
98    strictly_monotonic: true,
99    flat_segment_count: 0,
100    requested_max_error: 1,
101    achieved_max_error: 1,
102    worst_case_input: 500,
103    achieved_max_inverse_code_error: 0,
104};
105/// Optional observation-code guard for [`FRONT_END_LOW_DC`].
106///
107/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
108/// not inferred from the integer value. The runtime getter and this constant agree.
109pub const FRONT_END_LOW_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
110    code: 65535,
111    behavior: ObservationGuardBehavior::Error,
112});
113
114#[rustfmt::skip]
115static FRONT_END_MID_DC_INPUTS: [u16; 2] = [100, 400];
116#[rustfmt::skip]
117static FRONT_END_MID_DC_OUTPUTS: [i32; 2] = [800, 3201];
118/// Family: "front\_end".
119/// Selectors: "coupling" = "dc", "range" = "mid".
120/// "front\_end\_mid\_dc" sparse physical transfer function.
121///
122/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
123/// Representation: "scaled polynomial (3 coefficients, scale=8000/1000000)".
124/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
125/// Domain: 100..=400 "adc\_code"; output: "millivolt" x 1000.
126/// Knots: 2 (12 bytes array payload).
127/// Exhaustive numerical error: requested <= 1, achieved 0.600000 output quanta
128/// (conservative metadata bound 1) at input 250.
129/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
130/// Observation guard: code 65535 with Error behavior.
131/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
132#[rustfmt::skip]
133pub const FRONT_END_MID_DC: PiecewiseLinearTransfer<2> =
134PiecewiseLinearTransfer::new(&FRONT_END_MID_DC_INPUTS, &FRONT_END_MID_DC_OUTPUTS, MonotonicDirection::Increasing)
135.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
136.with_observation_guard(65535, ObservationGuardBehavior::Error);
137/// Metadata for [`FRONT_END_MID_DC`].
138pub const FRONT_END_MID_DC_METADATA: TransferMetadata = TransferMetadata {
139    input_unit: "adc_code",
140    output_unit: "millivolt",
141    output_scale: 1000,
142    domain_min: 100,
143    domain_max: 400,
144    range_min: 800,
145    range_max: 3201,
146    direction: MonotonicDirection::Increasing,
147    knot_count: 2,
148    strictly_monotonic: true,
149    flat_segment_count: 0,
150    requested_max_error: 1,
151    achieved_max_error: 1,
152    worst_case_input: 250,
153    achieved_max_inverse_code_error: 0,
154};
155/// Optional observation-code guard for [`FRONT_END_MID_DC`].
156///
157/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
158/// not inferred from the integer value. The runtime getter and this constant agree.
159pub const FRONT_END_MID_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
160    code: 65535,
161    behavior: ObservationGuardBehavior::Error,
162});
163
164#[rustfmt::skip]
165static GUARDED_IDENTITY_INPUTS: [u16; 2] = [1, 10];
166#[rustfmt::skip]
167static GUARDED_IDENTITY_OUTPUTS: [i32; 2] = [1, 10];
168/// "guarded\_identity" sparse physical transfer function.
169///
170/// Source provenance: none declared.
171/// Representation: "formula y = x".
172/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = error; above = clamp.
173/// Domain: 1..=10 "adc\_code"; output: "millivolt" x 1.
174/// Knots: 2 (12 bytes array payload).
175/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
176/// (conservative metadata bound 0) at input 1.
177/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
178/// Observation guard: code 65535 with Error behavior.
179/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
180#[rustfmt::skip]
181pub const GUARDED_IDENTITY: PiecewiseLinearTransfer<2> =
182PiecewiseLinearTransfer::new(&GUARDED_IDENTITY_INPUTS, &GUARDED_IDENTITY_OUTPUTS, MonotonicDirection::Increasing)
183.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
184.with_observation_guard(65535, ObservationGuardBehavior::Error);
Source

pub const fn with_flat_resolution(self, policy: FlatResolution) -> Self

Set how flat (equal-output) runs are resolved by invert.

Source

pub const fn with_observation_guard( self, code: u16, behavior: ObservationGuardBehavior, ) -> Self

Set an explicit observation-code guard independent of below / above.

The guarded code is classified before ordinary domain policy and is not mapped through inverse range behavior. Classification of a code as saturation is declared consumer/device policy, not inferred from the integer value.

§Panics

Panics while defining the table if code is not strictly above the fitted domain_max. Generated tables call this in a constant context, making an invalid guard a compile error.

Examples found in repository?
examples/../tests/fixtures/observation_guards_generated.rs (line 25)
22pub const GUARDED_ERROR: PiecewiseLinearTransfer<2> =
23PiecewiseLinearTransfer::new(&GUARDED_ERROR_INPUTS, &GUARDED_ERROR_OUTPUTS, MonotonicDirection::Increasing)
24.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
25.with_observation_guard(65535, ObservationGuardBehavior::Error);
26/// Metadata for [`GUARDED_ERROR`].
27pub const GUARDED_ERROR_METADATA: TransferMetadata = TransferMetadata {
28    input_unit: "count",
29    output_unit: "unit",
30    output_scale: 1,
31    domain_min: 1,
32    domain_max: 10,
33    range_min: 1,
34    range_max: 10,
35    direction: MonotonicDirection::Increasing,
36    knot_count: 2,
37    strictly_monotonic: true,
38    flat_segment_count: 0,
39    requested_max_error: 1,
40    achieved_max_error: 0,
41    worst_case_input: 1,
42    achieved_max_inverse_code_error: 0,
43};
44/// Optional observation-code guard for [`GUARDED_ERROR`].
45///
46/// Classification of a code as saturation is declared consumer/device policy,
47/// not inferred from the integer value. The runtime getter and this constant agree.
48pub const GUARDED_ERROR_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
49    code: 65535,
50    behavior: ObservationGuardBehavior::Error,
51});
52
53#[rustfmt::skip]
54static GUARDED_FAMILY_VARIANT_CLAMP_INPUTS: [u16; 2] = [1, 10];
55#[rustfmt::skip]
56static GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS: [i32; 2] = [10, 1];
57/// Family: "guarded\_family".
58/// Selectors: "variant" = "clamp".
59/// "guarded\_family\_variant\_clamp" sparse physical transfer function.
60///
61/// Source provenance: identity "test fixture".
62/// Representation: "formula y = 11 - x".
63/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = clamp; above = error.
64/// Domain: 1..=10 "count"; output: "unit" x 1.
65/// Knots: 2 (12 bytes array payload).
66/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
67/// (conservative metadata bound 0) at input 1.
68/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
69/// Observation guard: code 65535 with Clamp behavior.
70/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
71#[rustfmt::skip]
72pub const GUARDED_FAMILY_VARIANT_CLAMP: PiecewiseLinearTransfer<2> =
73PiecewiseLinearTransfer::new(&GUARDED_FAMILY_VARIANT_CLAMP_INPUTS, &GUARDED_FAMILY_VARIANT_CLAMP_OUTPUTS, MonotonicDirection::Decreasing)
74.with_boundaries(BoundaryBehavior::Clamp, BoundaryBehavior::Error)
75.with_observation_guard(65535, ObservationGuardBehavior::Clamp);
More examples
Hide additional examples
examples/../tests/fixtures/family_acceptance_generated.rs (line 36)
33pub const FRONT_END_HIGH_DC: PiecewiseLinearTransfer<2> =
34PiecewiseLinearTransfer::new(&FRONT_END_HIGH_DC_INPUTS, &FRONT_END_HIGH_DC_OUTPUTS, MonotonicDirection::Increasing)
35.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
36.with_observation_guard(65535, ObservationGuardBehavior::Error);
37/// Metadata for [`FRONT_END_HIGH_DC`].
38pub const FRONT_END_HIGH_DC_METADATA: TransferMetadata = TransferMetadata {
39    input_unit: "adc_code",
40    output_unit: "millivolt",
41    output_scale: 1000,
42    domain_min: 100,
43    domain_max: 250,
44    range_min: 3201,
45    range_max: 8006,
46    direction: MonotonicDirection::Increasing,
47    knot_count: 2,
48    strictly_monotonic: true,
49    flat_segment_count: 0,
50    requested_max_error: 1,
51    achieved_max_error: 1,
52    worst_case_input: 175,
53    achieved_max_inverse_code_error: 0,
54};
55/// Optional observation-code guard for [`FRONT_END_HIGH_DC`].
56///
57/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
58/// not inferred from the integer value. The runtime getter and this constant agree.
59pub const FRONT_END_HIGH_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
60    code: 65535,
61    behavior: ObservationGuardBehavior::Error,
62});
63
64#[rustfmt::skip]
65static FRONT_END_LOW_DC_INPUTS: [u16; 2] = [100, 500];
66#[rustfmt::skip]
67static FRONT_END_LOW_DC_OUTPUTS: [i32; 2] = [200, 1000];
68/// Family: "front\_end".
69/// Selectors: "coupling" = "dc", "range" = "low".
70/// "front\_end\_low\_dc" sparse physical transfer function.
71///
72/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
73/// Representation: "scaled polynomial (3 coefficients, scale=2000/1000000)".
74/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
75/// Domain: 100..=500 "adc\_code"; output: "millivolt" x 1000.
76/// Knots: 2 (12 bytes array payload).
77/// Exhaustive numerical error: requested <= 1, achieved 0.100000 output quanta
78/// (conservative metadata bound 1) at input 500.
79/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
80/// Observation guard: code 65535 with Error behavior.
81/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
82#[rustfmt::skip]
83pub const FRONT_END_LOW_DC: PiecewiseLinearTransfer<2> =
84PiecewiseLinearTransfer::new(&FRONT_END_LOW_DC_INPUTS, &FRONT_END_LOW_DC_OUTPUTS, MonotonicDirection::Increasing)
85.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
86.with_observation_guard(65535, ObservationGuardBehavior::Error);
87/// Metadata for [`FRONT_END_LOW_DC`].
88pub const FRONT_END_LOW_DC_METADATA: TransferMetadata = TransferMetadata {
89    input_unit: "adc_code",
90    output_unit: "millivolt",
91    output_scale: 1000,
92    domain_min: 100,
93    domain_max: 500,
94    range_min: 200,
95    range_max: 1000,
96    direction: MonotonicDirection::Increasing,
97    knot_count: 2,
98    strictly_monotonic: true,
99    flat_segment_count: 0,
100    requested_max_error: 1,
101    achieved_max_error: 1,
102    worst_case_input: 500,
103    achieved_max_inverse_code_error: 0,
104};
105/// Optional observation-code guard for [`FRONT_END_LOW_DC`].
106///
107/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
108/// not inferred from the integer value. The runtime getter and this constant agree.
109pub const FRONT_END_LOW_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
110    code: 65535,
111    behavior: ObservationGuardBehavior::Error,
112});
113
114#[rustfmt::skip]
115static FRONT_END_MID_DC_INPUTS: [u16; 2] = [100, 400];
116#[rustfmt::skip]
117static FRONT_END_MID_DC_OUTPUTS: [i32; 2] = [800, 3201];
118/// Family: "front\_end".
119/// Selectors: "coupling" = "dc", "range" = "mid".
120/// "front\_end\_mid\_dc" sparse physical transfer function.
121///
122/// Source provenance: identity "synthetic multi-range ADC note"; locator "Table 1".
123/// Representation: "scaled polynomial (3 coefficients, scale=8000/1000000)".
124/// Generation policy: requested interpolation error <= 1; max_knots = 32; below = error; above = clamp.
125/// Domain: 100..=400 "adc\_code"; output: "millivolt" x 1000.
126/// Knots: 2 (12 bytes array payload).
127/// Exhaustive numerical error: requested <= 1, achieved 0.600000 output quanta
128/// (conservative metadata bound 1) at input 250.
129/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
130/// Observation guard: code 65535 with Error behavior.
131/// Classification of this code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy, not inferred from the integer value.
132#[rustfmt::skip]
133pub const FRONT_END_MID_DC: PiecewiseLinearTransfer<2> =
134PiecewiseLinearTransfer::new(&FRONT_END_MID_DC_INPUTS, &FRONT_END_MID_DC_OUTPUTS, MonotonicDirection::Increasing)
135.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
136.with_observation_guard(65535, ObservationGuardBehavior::Error);
137/// Metadata for [`FRONT_END_MID_DC`].
138pub const FRONT_END_MID_DC_METADATA: TransferMetadata = TransferMetadata {
139    input_unit: "adc_code",
140    output_unit: "millivolt",
141    output_scale: 1000,
142    domain_min: 100,
143    domain_max: 400,
144    range_min: 800,
145    range_max: 3201,
146    direction: MonotonicDirection::Increasing,
147    knot_count: 2,
148    strictly_monotonic: true,
149    flat_segment_count: 0,
150    requested_max_error: 1,
151    achieved_max_error: 1,
152    worst_case_input: 250,
153    achieved_max_inverse_code_error: 0,
154};
155/// Optional observation-code guard for [`FRONT_END_MID_DC`].
156///
157/// Classification of a code as saturation is cited from identity "synthetic multi-range ADC note"; locator "§4 saturation" and applied as declared policy,
158/// not inferred from the integer value. The runtime getter and this constant agree.
159pub const FRONT_END_MID_DC_OBSERVATION_GUARD: Option<ObservationGuardMetadata> = Some(ObservationGuardMetadata {
160    code: 65535,
161    behavior: ObservationGuardBehavior::Error,
162});
163
164#[rustfmt::skip]
165static GUARDED_IDENTITY_INPUTS: [u16; 2] = [1, 10];
166#[rustfmt::skip]
167static GUARDED_IDENTITY_OUTPUTS: [i32; 2] = [1, 10];
168/// "guarded\_identity" sparse physical transfer function.
169///
170/// Source provenance: none declared.
171/// Representation: "formula y = x".
172/// Generation policy: requested interpolation error <= 1; max_knots = 8; below = error; above = clamp.
173/// Domain: 1..=10 "adc\_code"; output: "millivolt" x 1.
174/// Knots: 2 (12 bytes array payload).
175/// Exhaustive numerical error: requested <= 1, achieved 0.000000 output quanta
176/// (conservative metadata bound 0) at input 1.
177/// This is table/quantization error against the configured ideal source, not total sensor accuracy.
178/// Observation guard: code 65535 with Error behavior.
179/// Classification of this code as saturation is declared consumer/device policy, not inferred from the integer value.
180#[rustfmt::skip]
181pub const GUARDED_IDENTITY: PiecewiseLinearTransfer<2> =
182PiecewiseLinearTransfer::new(&GUARDED_IDENTITY_INPUTS, &GUARDED_IDENTITY_OUTPUTS, MonotonicDirection::Increasing)
183.with_boundaries(BoundaryBehavior::Error, BoundaryBehavior::Clamp)
184.with_observation_guard(65535, ObservationGuardBehavior::Error);
Source

pub const fn observation_guard(&self) -> Option<ObservationGuard>

Return the explicit observation-code guard, if one is set.

Source

pub const fn inputs(&self) -> &'static [u16; N]

Return the input knot array.

Source

pub const fn outputs(&self) -> &'static [i32; N]

Return the output knot array.

Source

pub const fn direction(&self) -> MonotonicDirection

Return the output monotonic direction.

Source

pub const fn below_behavior(&self) -> BoundaryBehavior

Return the below-observation-domain behavior.

Declared against the observation domain, not the physical range. For the physical-side policies used by inverse conversion, see range_behaviors.

Source

pub const fn above_behavior(&self) -> BoundaryBehavior

Return the above-observation-domain behavior.

Declared against the observation domain, not the physical range. For the physical-side policies used by inverse conversion, see range_behaviors.

Source

pub const fn flat_resolution(&self) -> FlatResolution

Return the flat-run resolution policy.

Source

pub const fn domain(&self) -> (u16, u16)

Return the inclusive input domain.

Source

pub const fn physical_range(&self) -> (i32, i32)

Return the inclusive physical output range as (min, max).

Source

pub fn invert_physical( &self, physical: i32, ) -> Result<u16, InverseTransferError<i32>>

Invert a physical measurement to an observation.

Convenience alias for InverseTransferFunction::invert.

Source

pub const fn range_behaviors(&self) -> (BoundaryBehavior, BoundaryBehavior)

Map the domain policies onto the physical range as (low_physical, high_physical).

below and above are declared against the observation domain, so on a decreasing table they swap: the codes above domain_max are the ones that produce physical values below range_min. Selecting by physical side alone would make a table configured below = Error, above = Clamp clamp in the forward direction and error in the inverse for the very same out-of-range condition.

Trait Implementations§

Source§

impl<const N: usize> Clone for PiecewiseLinearTransfer<N>

Source§

fn clone(&self) -> PiecewiseLinearTransfer<N>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const N: usize> Copy for PiecewiseLinearTransfer<N>

Source§

impl<const N: usize> Debug for PiecewiseLinearTransfer<N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const N: usize> InverseTransferFunction for PiecewiseLinearTransfer<N>

Source§

type Physical = i32

Physical measurement type (input to inverse).
Source§

type Observation = u16

Observation type (output of inverse).
Source§

fn invert(&self, physical: i32) -> Result<u16, InverseTransferError<i32>>

Invert a physical measurement to an observation. Read more
Source§

impl<const N: usize> TransferFunction for PiecewiseLinearTransfer<N>

Source§

type Input = u16

Input observation type.
Source§

type Output = i32

Output measurement type.
Source§

fn convert(&self, input: u16) -> Result<i32, TransferError<u16>>

Convert an observation to a measurement. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where Dst: LosslessTryFrom<Src>,

Source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
Source§

impl<Src, Dst> LossyInto<Dst> for Src
where Dst: LossyFrom<Src>,

Source§

fn lossy_into(self) -> Dst

Performs the conversion.
Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> StrictAs for T

Source§

fn strict_as<Dst>(self) -> Dst
where T: StrictCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> StrictCastFrom<Src> for Dst
where Src: StrictCast<Dst>,

Source§

fn strict_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.