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