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