Skip to main content

sva_samples/
error.rs

1// Concern: declares the refusals the sampled half reaches, each with its code | Non-concern: the closed-form crate's own codes (sva-formula), rendering a diagnostic (sva-engine) | IO: none
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub enum SampleError {
5    HopOutsideCola {
6        window: usize,
7        hop: usize,
8    },
9    WindowNotPowerOfTwo {
10        window: usize,
11    },
12    WidthMismatch {
13        left: usize,
14        right: usize,
15    },
16    ChannelOutOfRange {
17        k: usize,
18        width: usize,
19    },
20    /// A node's program writes another number of components than its own samples hold.
21    OwnWidth {
22        writes: usize,
23        holds: usize,
24    },
25    /// A grid sized from the rate and the fundamental, past what one call may allocate.
26    GridTooLarge {
27        model: &'static str,
28        nodes: usize,
29        ceiling: usize,
30    },
31    /// A string no stable grid at this rate rings at the partials it was asked for.
32    StringPastRate {
33        model: &'static str,
34    },
35    /// A unison whose bridge row leaves its scheme's mass form not provably positive.
36    BridgeUnstable {
37        model: &'static str,
38    },
39    /// A contact whose force solve settled on no value at a sample.
40    ContactUnsettled {
41        model: &'static str,
42        sample: usize,
43    },
44    /// A reading needs a sample this run has not computed yet.
45    ReadsAhead {
46        at: i64,
47    },
48    /// An exactly computed time passed what its integers hold.
49    UnreadablePosition,
50    /// A closed form read at one of the machine's instants has no value there.
51    FormulaUnevaluable {
52        at: i64,
53    },
54    /// A varying parameter outside the range its model holds, at one sample.
55    ArgumentOutOfRange {
56        model: &'static str,
57        name: &'static str,
58        /// The value's bits, which keep the error `Eq`.
59        bits: u64,
60        sample: u64,
61    },
62}
63
64/// What a collapse refuses, per FORMAT 16.3.
65#[derive(Clone, Debug, PartialEq)]
66pub enum CollapseError {
67    SingularInCt {
68        at: f64,
69        order: i32,
70    },
71    NotEvaluable(&'static str),
72    /// `terms` is `None` where the count is past what a `usize` holds.
73    NestedSeries {
74        depth: usize,
75        terms: Option<usize>,
76        bound: usize,
77    },
78    LeftAlgebra(&'static str),
79    /// A form in `f` reaches the grid by one transform over a whole extent.
80    NoBlockRow,
81}
82
83impl CollapseError {
84    pub fn code(&self) -> &'static str {
85        match self {
86            CollapseError::SingularInCt { .. } => "collapse.singular_in_ct",
87            CollapseError::NotEvaluable(_) => "collapse.not_evaluable",
88            CollapseError::NestedSeries { .. } => "collapse.series_nesting",
89            CollapseError::LeftAlgebra(_) => "cast.left_algebra",
90            CollapseError::NoBlockRow => "collapse.no_block_row",
91        }
92    }
93}
94
95/// One repair per refusal.
96impl CollapseError {
97    pub fn help(&self) -> &'static str {
98        match self {
99            CollapseError::SingularInCt { .. } => {
100                "write it inside a convolution, or sample the closed form it multiplies"
101            }
102            CollapseError::NestedSeries { .. } => {
103                "write fewer levels, or a narrower band for the terms to clear"
104            }
105            CollapseError::NotEvaluable(_) | CollapseError::LeftAlgebra(_) => {
106                "write the subterm inside sample(...) to leave A deliberately"
107            }
108            CollapseError::NoBlockRow => {
109                "render it to a stated end instead of streaming it, or write it in t"
110            }
111        }
112    }
113}
114
115impl std::fmt::Display for CollapseError {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        match self {
118            CollapseError::SingularInCt { at, order } => write!(
119                f,
120                "a singularity of order {order} at t = {at} has no value on the grid"
121            ),
122            CollapseError::NotEvaluable(what) => {
123                write!(f, "{what} has no value at a point")
124            }
125            CollapseError::NestedSeries {
126                depth,
127                terms,
128                bound,
129            } => match terms {
130                Some(terms) => write!(
131                    f,
132                    "a series nested {depth} deep takes {terms} terms at one instant, past \
133                     the {bound} one expansion holds"
134                ),
135                None => write!(
136                    f,
137                    "a series nested {depth} deep takes more terms at one instant than a \
138                     count holds, past the {bound} one expansion holds"
139                ),
140            },
141            CollapseError::LeftAlgebra(clause) => write!(f, "the closed form left A. {clause}"),
142            CollapseError::NoBlockRow => write!(
143                f,
144                "a closed form in f reaches the grid by one transform over a whole extent, \
145                 so no block of it is read alone"
146            ),
147        }
148    }
149}
150
151impl SampleError {
152    pub fn code(&self) -> &'static str {
153        match self {
154            SampleError::HopOutsideCola { .. } => "samples.hop_outside_cola",
155            SampleError::WindowNotPowerOfTwo { .. } => "samples.window_not_power_of_two",
156            SampleError::WidthMismatch { .. } => "type.width_mismatch",
157            SampleError::ChannelOutOfRange { .. } => "samples.channel_out_of_range",
158            SampleError::OwnWidth { .. } => "samples.own_width",
159            SampleError::GridTooLarge { .. } => "samples.grid_too_large",
160            SampleError::StringPastRate { .. } => "samples.string_past_rate",
161            SampleError::BridgeUnstable { .. } => "samples.bridge_unstable",
162            SampleError::ContactUnsettled { .. } => "samples.contact_unsettled",
163            SampleError::ArgumentOutOfRange { .. } => "samples.argument_out_of_range",
164            SampleError::ReadsAhead { .. } => "engine.reads_ahead",
165            SampleError::UnreadablePosition => "engine.unreadable_position",
166            SampleError::FormulaUnevaluable { .. } => "collapse.not_evaluable",
167        }
168    }
169}
170
171impl std::fmt::Display for SampleError {
172    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
173        match self {
174            SampleError::HopOutsideCola { window, hop } => write!(
175                f,
176                "a window of {window} at a hop of {hop} does not overlap-add to a constant. \
177                 write a hop that divides the window"
178            ),
179            SampleError::WindowNotPowerOfTwo { window } => {
180                write!(f, "a window of {window} is not a power of two")
181            }
182            SampleError::WidthMismatch { left, right } => write!(
183                f,
184                "{left} components meet {right}; an elementwise operation needs equal widths, \
185                 or one side mono"
186            ),
187            SampleError::ChannelOutOfRange { k, width } => {
188                write!(f, "component {k} of a value {width} wide")
189            }
190            SampleError::OwnWidth { writes, holds } => write!(
191                f,
192                "a node's program writes {writes} components into samples {holds} wide; the \
193                 engine built it at another width than its type, a defect in the engine and \
194                 not in the composition"
195            ),
196            SampleError::GridTooLarge {
197                model,
198                nodes,
199                ceiling,
200            } => write!(
201                f,
202                "`{model}` sizes a {nodes}-node grid at this rate, past the {ceiling} one \
203                 call may hold. ask for a higher fundamental, or a lower --rate"
204            ),
205            SampleError::StringPastRate { model } => write!(
206                f,
207                "`{model}` has no stable grid at this rate whose first two partials ring where \
208                 asked. ask for a lower fundamental or `b`, or a higher --rate"
209            ),
210            SampleError::BridgeUnstable { model } => write!(
211                f,
212                "`{model}`'s unison is not proven stable on its bridge at this rate: the mass \
213                 form its bridge row leaves is not provably positive. ask for a heavier bridge, \
214                 less frequency-dependent loss, or a higher --rate"
215            ),
216            SampleError::ContactUnsettled { model, sample } => write!(
217                f,
218                "`{model}`'s contact force settled on no value at sample {sample}. ask for a \
219                 lower bow velocity or force, or a higher --rate"
220            ),
221            SampleError::ReadsAhead { at } => write!(
222                f,
223                "a reading needs sample {at} of its source, which is not computed yet: a \
224                 stream reads no output ahead of where it stands"
225            ),
226            SampleError::UnreadablePosition => {
227                write!(f, "an exactly computed time passed what its integers hold")
228            }
229            SampleError::FormulaUnevaluable { at } => write!(
230                f,
231                "a closed form read at sample {at}'s instant has no value there"
232            ),
233            SampleError::ArgumentOutOfRange {
234                model,
235                name,
236                bits,
237                sample,
238            } => write!(
239                f,
240                "`{model}`'s `{name}` is {} at sample {sample}, outside the range it models",
241                f64::from_bits(*bits)
242            ),
243        }
244    }
245}