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>
impl<const N: usize> PiecewiseLinearTransfer<N>
Sourcepub const fn new(
inputs: &'static [u16; N],
outputs: &'static [i32; N],
direction: MonotonicDirection,
) -> Self
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?
More examples
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);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);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}Sourcepub const fn with_boundaries(
self,
below: BoundaryBehavior,
above: BoundaryBehavior,
) -> Self
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?
More examples
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);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);Sourcepub const fn with_flat_resolution(self, policy: FlatResolution) -> Self
pub const fn with_flat_resolution(self, policy: FlatResolution) -> Self
Set how flat (equal-output) runs are resolved by invert.
Sourcepub const fn with_observation_guard(
self,
code: u16,
behavior: ObservationGuardBehavior,
) -> Self
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?
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
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);Sourcepub const fn observation_guard(&self) -> Option<ObservationGuard>
pub const fn observation_guard(&self) -> Option<ObservationGuard>
Return the explicit observation-code guard, if one is set.
Sourcepub const fn direction(&self) -> MonotonicDirection
pub const fn direction(&self) -> MonotonicDirection
Return the output monotonic direction.
Sourcepub const fn below_behavior(&self) -> BoundaryBehavior
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.
Sourcepub const fn above_behavior(&self) -> BoundaryBehavior
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.
Sourcepub const fn flat_resolution(&self) -> FlatResolution
pub const fn flat_resolution(&self) -> FlatResolution
Return the flat-run resolution policy.
Sourcepub const fn physical_range(&self) -> (i32, i32)
pub const fn physical_range(&self) -> (i32, i32)
Return the inclusive physical output range as (min, max).
Sourcepub fn invert_physical(
&self,
physical: i32,
) -> Result<u16, InverseTransferError<i32>>
pub fn invert_physical( &self, physical: i32, ) -> Result<u16, InverseTransferError<i32>>
Invert a physical measurement to an observation.
Convenience alias for InverseTransferFunction::invert.
Sourcepub const fn range_behaviors(&self) -> (BoundaryBehavior, BoundaryBehavior)
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>
impl<const N: usize> Clone for PiecewiseLinearTransfer<N>
Source§fn clone(&self) -> PiecewiseLinearTransfer<N>
fn clone(&self) -> PiecewiseLinearTransfer<N>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more