1use super::CompiledOps;
4use super::ops::{self, Layout};
5use super::renderer::{Index, NodeRenderer, Slot};
6use crate::error::SampleError;
7use crate::grid::Extent;
8
9#[derive(Clone)]
10pub struct Span {
11 pub from: i64,
12 pub to: i64,
13 pub renderer: NodeRenderer,
14}
15
16#[derive(Clone)]
19pub struct Spanned {
20 spans: Vec<(Span, CompiledOps)>,
21 layout: Layout,
22}
23
24impl Spanned {
25 pub fn new(
27 renderer: &NodeRenderer,
28 layout: &Layout,
29 (from, to): (i64, i64),
30 live: &[Extent],
31 ) -> Result<Spanned, SampleError> {
32 let spans = renderer
33 .spans(layout, (from, to), live)?
34 .into_iter()
35 .map(|span| {
36 let compiled_ops = span.renderer.compile(layout)?;
37 Ok((span, compiled_ops))
38 })
39 .collect::<Result<_, SampleError>>()?;
40 Ok(Spanned {
41 spans,
42 layout: layout.clone(),
43 })
44 }
45
46 pub fn spans(&self) -> impl Iterator<Item = &Span> {
47 self.spans.iter().map(|(span, _)| span)
48 }
49
50 pub(super) fn grid(&self) -> crate::grid::Grid {
51 self.layout.grid
52 }
53
54 pub(super) fn compiled(&self) -> &[(Span, CompiledOps)] {
55 &self.spans
56 }
57
58 pub(super) fn silent(&self) -> Result<CompiledOps, SampleError> {
60 NodeRenderer::zeros(self.layout.width).compile(&self.layout)
61 }
62}
63
64impl NodeRenderer {
65 pub fn spans(
68 &self,
69 layout: &Layout,
70 (from, to): (i64, i64),
71 live: &[Extent],
72 ) -> Result<Vec<Span>, SampleError> {
73 let mut root = Cut::of(self, layout, live)?;
74 let mut edges = vec![from, to];
75 root.edges(&mut edges);
76 edges.retain(|e| from <= *e && *e <= to);
77 edges.sort_unstable();
78 edges.dedup();
79 let mut out: Vec<Span> = Vec::new();
80 for pair in edges.windows(2) {
81 let span = Extent::new(pair[0], pair[1]);
82 let changed = root.strip_exact_zeros(span, layout)?;
83 match out.last_mut() {
84 Some(last) if !changed => last.to = span.end,
85 last => {
86 let renderer = root.made();
87 match last {
88 Some(last) if last.renderer == renderer => last.to = span.end,
89 _ => out.push(Span {
90 from: span.start,
91 to: span.end,
92 renderer,
93 }),
94 }
95 }
96 }
97 }
98 Ok(out)
99 }
100
101 pub fn stepwise(&self, beside: &dyn Fn(Slot) -> bool) -> NodeRenderer {
104 match self {
105 NodeRenderer::Indexed {
106 slot,
107 index,
108 reach: None,
109 } if beside(*slot) => NodeRenderer::Indexed {
110 slot: *slot,
111 index: index.clone(),
112 reach: Some((i64::MIN, 0)),
113 },
114 other => rebuilt(other, &mut |p| p.stepwise(beside)),
115 }
116 }
117}
118
119struct Cut<'r> {
123 node: &'r NodeRenderer,
124 width: usize,
125 operands: Vec<Cut<'r>>,
126 reach: Option<Extent>,
128 until: i64,
129 made: Made,
130 held: Held,
131}
132
133#[derive(Clone, PartialEq)]
134enum Made {
135 Kept,
136 Zeros,
138 Terms(Vec<usize>),
140 Minuend,
142}
143
144#[derive(Default)]
146struct Held {
147 zero: bool,
149 nil: bool,
151 stateless: bool,
152 constant: Option<Vec<f64>>,
154}
155
156impl<'r> Cut<'r> {
157 fn of(
158 node: &'r NodeRenderer,
159 layout: &Layout,
160 live: &[Extent],
161 ) -> Result<Cut<'r>, SampleError> {
162 let operands = node
163 .operands()
164 .into_iter()
165 .map(|p| Cut::of(p, layout, live))
166 .collect::<Result<Vec<_>, _>>()?;
167 let widths: Vec<usize> = operands.iter().map(|o| o.width).collect();
168 let reach = match node {
169 NodeRenderer::Read {
170 slot: Slot::Read(id),
171 map,
172 } => Some(map.preimage(live[id.0 as usize])),
173 _ => None,
174 };
175 Ok(Cut {
176 node,
177 width: ops::width(node, &widths, layout)?,
178 operands,
179 reach,
180 until: i64::MIN,
181 made: Made::Kept,
182 held: Held::default(),
183 })
184 }
185
186 fn edges(&self, out: &mut Vec<i64>) {
187 if let Some(reach) = self.reach {
188 out.extend([reach.start, reach.end]);
189 }
190 if let NodeRenderer::Crop { window, .. } = self.node {
191 out.extend([window.0, window.1]);
192 }
193 for o in &self.operands {
194 o.edges(out);
195 }
196 }
197
198 fn strip_exact_zeros(&mut self, span: Extent, layout: &Layout) -> Result<bool, SampleError> {
201 if span.end <= self.until {
202 return Ok(false);
203 }
204 let mut below = false;
205 for o in &mut self.operands {
206 below |= o.strip_exact_zeros(span, layout)?;
207 }
208 let mut until = self
209 .operands
210 .iter()
211 .map(|o| o.until)
212 .min()
213 .unwrap_or(i64::MAX);
214 let over = |e: Extent| {
215 [e.start, e.end]
216 .into_iter()
217 .filter(|&x| x > span.start)
218 .min()
219 };
220 let shut = match self.node {
221 NodeRenderer::Crop { window, .. } => {
222 let open = Extent::new(window.0.min(window.1), window.1);
223 until = until.min(over(open).unwrap_or(i64::MAX));
224 open.intersect(span).is_empty()
225 }
226 _ => false,
227 };
228 let dead = self.reach.is_some_and(|reach| {
229 until = until.min(over(reach).unwrap_or(i64::MAX));
230 reach.intersect(span).is_empty()
231 });
232 let made = self.decided(shut, layout)?;
233 let changed = self.until == i64::MIN || made != self.made || (below && made != Made::Zeros);
234 self.held = self.holding(&made, shut, dead);
235 self.made = made;
236 self.until = until;
237 Ok(changed)
238 }
239
240 fn decided(&self, shut: bool, layout: &Layout) -> Result<Made, SampleError> {
244 let ops = &self.operands;
245 Ok(match self.node {
246 NodeRenderer::Crop { .. } if shut && ops[0].held.stateless => Made::Zeros,
247 NodeRenderer::Mul(_)
248 if ops.iter().any(|o| o.held.zero) && ops.iter().all(|o| o.held.stateless) =>
249 {
250 Made::Zeros
251 }
252 NodeRenderer::Add(_) => {
253 let live: Vec<usize> = (0..ops.len()).filter(|&k| !ops[k].held.nil).collect();
254 let widths: Vec<usize> = live.iter().map(|&k| ops[k].width).collect();
255 match live.is_empty() {
256 true if self.width == 1 => Made::Zeros,
257 false if live.len() == ops.len() => Made::Kept,
258 false if ops::width(self.node, &widths, layout)? == self.width => {
259 Made::Terms(live)
260 }
261 _ => Made::Kept,
262 }
263 }
264 NodeRenderer::Sub(..) if ops[1].held.zero && ops[0].width == self.width => {
265 Made::Minuend
266 }
267 _ => Made::Kept,
268 })
269 }
270
271 fn holding(&self, made: &Made, shut: bool, dead: bool) -> Held {
272 let ops = &self.operands;
273 let of = |k: usize| &ops[k].held;
274 match made {
275 Made::Zeros => Held {
276 zero: true,
277 nil: true,
278 stateless: true,
279 constant: Some(vec![0.0; self.width]),
280 },
281 Made::Minuend => Held {
282 zero: of(0).zero,
283 nil: of(0).nil,
284 stateless: of(0).stateless,
285 constant: of(0).constant.clone(),
286 },
287 Made::Terms(live) => {
288 let zero = live.iter().all(|&k| of(k).nil);
289 Held {
290 zero,
291 nil: zero,
292 stateless: live.iter().all(|&k| of(k).stateless),
293 constant: fold(live.iter().map(|&k| of(k)), 0.0, |a, b| a + b),
294 }
295 }
296 Made::Kept => {
297 let all = |f: fn(&Held) -> bool| ops.iter().all(|o| f(&o.held));
298 let zero = match self.node {
299 NodeRenderer::Read {
300 slot: Slot::Read(_),
301 ..
302 } => dead,
303 NodeRenderer::Const(v) => v.to_bits() == 0,
304 NodeRenderer::Crop { .. } => shut || of(0).zero,
305 NodeRenderer::Add(_) => all(|h| h.nil),
306 NodeRenderer::Join(_) => all(|h| h.zero),
307 NodeRenderer::Sub(..) => of(0).zero && of(1).zero,
308 _ => false,
309 };
310 let nil = match self.node {
311 NodeRenderer::Mul(_) => match ops.iter().position(|o| o.held.nil) {
312 None => false,
313 Some(at) => {
314 finite(fold(ops[..at].iter().map(|o| &o.held), 1.0, |a, b| a * b))
315 && ops[at + 1..]
316 .iter()
317 .all(|o| o.held.nil || finite(o.held.constant.clone()))
318 }
319 },
320 NodeRenderer::Crop { .. } => zero || of(0).nil,
321 _ => zero,
322 };
323 let held = ops.iter().map(|o| &o.held);
324 let constant = match self.node {
325 NodeRenderer::Const(v) => Some(vec![*v]),
326 NodeRenderer::Join(_) => {
327 held.map(|h| h.constant.clone())
328 .try_fold(Vec::new(), |mut all, c| {
329 all.extend(c?);
330 Some(all)
331 })
332 }
333 NodeRenderer::Add(_) => fold(held, 0.0, |a, b| a + b),
334 NodeRenderer::Mul(_) => fold(held, 1.0, |a, b| a * b),
335 _ => None,
336 };
337 Held {
338 zero,
339 nil,
340 stateless: !self.node.holds_state() && all(|h| h.stateless),
341 constant,
342 }
343 }
344 }
345 }
346
347 fn made(&self) -> NodeRenderer {
348 match &self.made {
349 Made::Zeros => NodeRenderer::zeros(self.width),
350 Made::Minuend => self.operands[0].made(),
351 Made::Terms(live) => {
352 NodeRenderer::Add(live.iter().map(|&k| self.operands[k].made()).collect())
353 }
354 Made::Kept => {
355 let mut each = self.operands.iter();
356 rebuilt(self.node, &mut |_| {
357 each.next().expect("one per operand").made()
358 })
359 }
360 }
361 }
362}
363
364fn finite(value: Option<Vec<f64>>) -> bool {
365 value.is_some_and(|v| v.iter().all(|x| x.is_finite()))
366}
367
368fn fold<'h>(
370 set: impl Iterator<Item = &'h Held>,
371 start: f64,
372 op: fn(f64, f64) -> f64,
373) -> Option<Vec<f64>> {
374 let values = set
375 .map(|h| h.constant.as_deref())
376 .collect::<Option<Vec<_>>>()?;
377 let width = values.iter().map(|v| v.len()).max().unwrap_or(1);
378 Some(
379 (0..width)
380 .map(|c| {
381 values
382 .iter()
383 .fold(start, |acc, v| op(acc, super::part(v, c)))
384 })
385 .collect(),
386 )
387}
388
389fn rebuilt(r: &NodeRenderer, each: &mut dyn FnMut(&NodeRenderer) -> NodeRenderer) -> NodeRenderer {
390 let mut one = |p: &NodeRenderer| Box::new(each(p));
391 match r {
392 NodeRenderer::Add(set) => NodeRenderer::Add(set.iter().map(&mut *each).collect()),
393 NodeRenderer::Mul(set) => NodeRenderer::Mul(set.iter().map(&mut *each).collect()),
394 NodeRenderer::Join(set) => NodeRenderer::Join(set.iter().map(&mut *each).collect()),
395 NodeRenderer::Sub(a, b) => NodeRenderer::Sub(one(a), one(b)),
396 NodeRenderer::Div(a, b) => NodeRenderer::Div(one(a), one(b)),
397 NodeRenderer::Pow(a, b) => NodeRenderer::Pow(one(a), one(b)),
398 NodeRenderer::Zip(f, a, b) => NodeRenderer::Zip(*f, one(a), one(b)),
399 NodeRenderer::Map(f, x) => NodeRenderer::Map(*f, one(x)),
400 NodeRenderer::Channel { x, k } => NodeRenderer::Channel { x: one(x), k: *k },
401 NodeRenderer::Crop {
402 x,
403 window,
404 a,
405 b,
406 rise,
407 fall,
408 } => NodeRenderer::Crop {
409 x: one(x),
410 window: *window,
411 a: *a,
412 b: *b,
413 rise: *rise,
414 fall: *fall,
415 },
416 NodeRenderer::Filter {
417 site,
418 from,
419 x,
420 cutoff,
421 q,
422 gain,
423 } => NodeRenderer::Filter {
424 site: *site,
425 from: *from,
426 x: one(x),
427 cutoff: one(cutoff),
428 q: one(q),
429 gain: one(gain),
430 },
431 NodeRenderer::Physics { site, from, args } => NodeRenderer::Physics {
432 site: *site,
433 from: *from,
434 args: args.iter().map(&mut *each).collect(),
435 },
436 NodeRenderer::Formula {
437 formula,
438 width,
439 time,
440 } => NodeRenderer::Formula {
441 formula: formula.clone(),
442 width: *width,
443 time: one(time),
444 },
445 NodeRenderer::Indexed { slot, index, reach } => NodeRenderer::Indexed {
446 slot: *slot,
447 index: held(index, &mut one),
448 reach: *reach,
449 },
450 NodeRenderer::Instant(index) => NodeRenderer::Instant(held(index, &mut one)),
451 leaf => leaf.clone(),
452 }
453}
454
455fn held(index: &Index, one: &mut dyn FnMut(&NodeRenderer) -> Box<NodeRenderer>) -> Index {
456 let mapped = index.mapped(&mut |t| Ok::<_, std::convert::Infallible>(one(t)));
457 match mapped {
458 Ok(index) => index,
459 }
460}