1#[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 GridTooLarge {
22 model: &'static str,
23 nodes: usize,
24 ceiling: usize,
25 },
26 StringPastRate {
28 model: &'static str,
29 },
30 BridgeUnstable {
32 model: &'static str,
33 },
34 ContactUnsettled {
36 model: &'static str,
37 sample: usize,
38 },
39 ReadsAhead {
41 at: i64,
42 },
43 UnreadablePosition,
45 FormulaUnevaluable {
47 at: i64,
48 },
49 ArgumentOutOfRange {
51 model: &'static str,
52 name: &'static str,
53 bits: u64,
55 sample: u64,
56 },
57}
58
59#[derive(Clone, Debug, PartialEq)]
61pub enum CollapseError {
62 EmptyBand {
63 ceiling: f64,
64 lowest: f64,
65 },
66 SingularInCt {
67 at: f64,
68 order: i32,
69 },
70 NotEvaluable(&'static str),
71 NestedSeries {
73 depth: usize,
74 terms: Option<usize>,
75 bound: usize,
76 },
77 LeftAlgebra(&'static str),
78 NoBlockRow,
80}
81
82impl CollapseError {
83 pub fn code(&self) -> &'static str {
84 match self {
85 CollapseError::EmptyBand { .. } => "collapse.empty_band",
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
95impl CollapseError {
97 pub fn help(&self) -> &'static str {
98 match self {
99 CollapseError::EmptyBand { ceiling, .. }
100 if *ceiling < sva_formula::AUDIBLE_CEILING_HZ =>
101 {
102 "this rate's own half is the ceiling: raise --rate past twice the \
103 lowest line"
104 }
105 CollapseError::EmptyBand { .. } => {
106 "the profile's 20 kHz ceiling is what no rate raises; read it with \
107 `--representation lines`, or bring the line into the band"
108 }
109 CollapseError::SingularInCt { .. } => {
110 "write it inside a convolution, or sample the closed form it multiplies"
111 }
112 CollapseError::NestedSeries { .. } => {
113 "write fewer levels, or a narrower band for the terms to clear"
114 }
115 CollapseError::NotEvaluable(_) | CollapseError::LeftAlgebra(_) => {
116 "write the subterm inside sample(...) to leave A deliberately"
117 }
118 CollapseError::NoBlockRow => {
119 "render it to a stated end instead of streaming it, or write it in t"
120 }
121 }
122 }
123}
124
125impl std::fmt::Display for CollapseError {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 match self {
128 CollapseError::EmptyBand { ceiling, lowest } => write!(
129 f,
130 "every line is at or above the {ceiling} Hz ceiling, the lowest at {lowest} Hz"
131 ),
132 CollapseError::SingularInCt { at, order } => write!(
133 f,
134 "a singularity of order {order} at t = {at} has no value on the grid"
135 ),
136 CollapseError::NotEvaluable(what) => {
137 write!(f, "{what} has no value at a point")
138 }
139 CollapseError::NestedSeries {
140 depth,
141 terms,
142 bound,
143 } => match terms {
144 Some(terms) => write!(
145 f,
146 "a series nested {depth} deep takes {terms} terms at one instant, past \
147 the {bound} one expansion holds"
148 ),
149 None => write!(
150 f,
151 "a series nested {depth} deep takes more terms at one instant than a \
152 count holds, past the {bound} one expansion holds"
153 ),
154 },
155 CollapseError::LeftAlgebra(clause) => write!(f, "the closed form left A. {clause}"),
156 CollapseError::NoBlockRow => write!(
157 f,
158 "a closed form in f reaches the grid by one transform over a whole extent, \
159 so no block of it is read alone"
160 ),
161 }
162 }
163}
164
165impl SampleError {
166 pub fn code(&self) -> &'static str {
167 match self {
168 SampleError::HopOutsideCola { .. } => "samples.hop_outside_cola",
169 SampleError::WindowNotPowerOfTwo { .. } => "samples.window_not_power_of_two",
170 SampleError::WidthMismatch { .. } => "type.width_mismatch",
171 SampleError::ChannelOutOfRange { .. } => "samples.channel_out_of_range",
172 SampleError::GridTooLarge { .. } => "samples.grid_too_large",
173 SampleError::StringPastRate { .. } => "samples.string_past_rate",
174 SampleError::BridgeUnstable { .. } => "samples.bridge_unstable",
175 SampleError::ContactUnsettled { .. } => "samples.contact_unsettled",
176 SampleError::ArgumentOutOfRange { .. } => "samples.argument_out_of_range",
177 SampleError::ReadsAhead { .. } => "engine.reads_ahead",
178 SampleError::UnreadablePosition => "engine.unreadable_position",
179 SampleError::FormulaUnevaluable { .. } => "collapse.not_evaluable",
180 }
181 }
182}
183
184impl std::fmt::Display for SampleError {
185 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
186 match self {
187 SampleError::HopOutsideCola { window, hop } => write!(
188 f,
189 "a window of {window} at a hop of {hop} does not overlap-add to a constant. \
190 write a hop that divides the window"
191 ),
192 SampleError::WindowNotPowerOfTwo { window } => {
193 write!(f, "a window of {window} is not a power of two")
194 }
195 SampleError::WidthMismatch { left, right } => write!(
196 f,
197 "{left} components meet {right}; an elementwise operation needs equal widths, \
198 or one side mono"
199 ),
200 SampleError::ChannelOutOfRange { k, width } => {
201 write!(f, "component {k} of a value {width} wide")
202 }
203 SampleError::GridTooLarge {
204 model,
205 nodes,
206 ceiling,
207 } => write!(
208 f,
209 "`{model}` sizes a {nodes}-node grid at this rate, past the {ceiling} one \
210 call may hold. ask for a higher fundamental, or a lower --rate"
211 ),
212 SampleError::StringPastRate { model } => write!(
213 f,
214 "`{model}` has no stable grid at this rate whose first two partials ring where \
215 asked. ask for a lower fundamental or `b`, or a higher --rate"
216 ),
217 SampleError::BridgeUnstable { model } => write!(
218 f,
219 "`{model}`'s unison is not proven stable on its bridge at this rate: the mass \
220 form its bridge row leaves is not provably positive. ask for a heavier bridge, \
221 less frequency-dependent loss, or a higher --rate"
222 ),
223 SampleError::ContactUnsettled { model, sample } => write!(
224 f,
225 "`{model}`'s contact force settled on no value at sample {sample}. ask for a \
226 lower bow velocity or force, or a higher --rate"
227 ),
228 SampleError::ReadsAhead { at } => write!(
229 f,
230 "a reading needs sample {at} of its source, which is not computed yet: a \
231 stream reads no output ahead of where it stands"
232 ),
233 SampleError::UnreadablePosition => {
234 write!(f, "an exactly computed time passed what its integers hold")
235 }
236 SampleError::FormulaUnevaluable { at } => write!(
237 f,
238 "a closed form read at sample {at}'s instant has no value there"
239 ),
240 SampleError::ArgumentOutOfRange {
241 model,
242 name,
243 bits,
244 sample,
245 } => write!(
246 f,
247 "`{model}`'s `{name}` is {} at sample {sample}, outside the range it models",
248 f64::from_bits(*bits)
249 ),
250 }
251 }
252}