Skip to main content

sva_samples/machine/
tape.rs

1// Concern: one node's output over a trailing span of the grid, and a view of any span | Non-concern: what writes it, how far back a reader reaches | IO: (component, index) -> f64
2
3use crate::buffer::Buffer;
4
5/// Samples `[base, end)` of one node's output, indexed from the grid's first sample.
6#[derive(Clone, Debug, PartialEq)]
7pub struct Tape {
8    planes: Vec<Vec<f64>>,
9    base: usize,
10}
11
12impl Tape {
13    pub fn new(width: usize, capacity: usize) -> Tape {
14        Tape::starting_at(width, capacity, 0)
15    }
16
17    pub fn starting_at(width: usize, capacity: usize, base: usize) -> Tape {
18        Tape {
19            planes: (0..width.max(1))
20                .map(|_| Vec::with_capacity(capacity))
21                .collect(),
22            base,
23        }
24    }
25
26    pub fn width(&self) -> usize {
27        self.planes.len()
28    }
29
30    pub fn base(&self) -> usize {
31        self.base
32    }
33
34    pub fn capacity(&self) -> usize {
35        self.planes[0].capacity()
36    }
37
38    pub fn end(&self) -> usize {
39        self.base + self.planes[0].len()
40    }
41
42    pub fn window(&self) -> Window<'_> {
43        Window {
44            planes: &self.planes,
45            base: self.base,
46        }
47    }
48
49    pub fn since(&self, c: usize, from: usize) -> &[f64] {
50        &self.planes[c][from - self.base..]
51    }
52
53    pub fn push(&mut self, c: usize, value: f64) {
54        self.planes[c].push(value);
55    }
56
57    pub fn forget_before(&mut self, from: usize) {
58        let gone = from.saturating_sub(self.base).min(self.planes[0].len());
59        if gone == 0 {
60            return;
61        }
62        for plane in &mut self.planes {
63            plane.drain(..gone);
64        }
65        self.base += gone;
66    }
67
68    pub fn into_planes(self) -> Vec<Vec<f64>> {
69        self.planes
70    }
71}
72
73#[derive(Clone, Copy, Debug)]
74pub struct Window<'a> {
75    planes: &'a [Vec<f64>],
76    base: usize,
77}
78
79impl<'a> Window<'a> {
80    pub fn of(buffer: &'a Buffer) -> Window<'a> {
81        Window {
82            planes: &buffer.planes,
83            base: 0,
84        }
85    }
86
87    /// A forgotten sample panics: some reader reaches further back than the tape keeps.
88    pub fn at(&self, c: usize, k: i64) -> f64 {
89        let Ok(k) = usize::try_from(k) else {
90            return 0.0;
91        };
92        let j = k.checked_sub(self.base).unwrap_or_else(|| {
93            panic!(
94                "sample {k} was forgotten; this tape keeps from {}",
95                self.base
96            )
97        });
98        self.planes[c].get(j).copied().unwrap_or(0.0)
99    }
100}