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