1mod block;
4mod live;
5pub mod ops;
6mod read;
7pub mod renderer;
8pub mod tape;
9
10use crate::error::SampleError;
11use crate::filters::FilterSite;
12use crate::physics::{Solver, site};
13use block::{BLOCK, Block, Here};
14use ops::{Layout, Op, lowered};
15use renderer::{Formula, Grid, Index, NodeRenderer, Site, Slot};
16use tape::{Tape, Window};
17
18pub use live::{Span, Spanned};
19
20pub use ops::Layout as MachineLayout;
21
22#[derive(Clone)]
25pub(super) struct Program {
26 ops: Vec<Op>,
27 widths: Vec<usize>,
28 args: Vec<Vec<usize>>,
29 formulas: Vec<Formula>,
30 indices: Vec<Index<usize>>,
31 sites: Vec<Site>,
32 pub width: usize,
33}
34
35impl NodeRenderer {
36 pub(super) fn compile(&self, layout: &Layout) -> Result<Program, SampleError> {
37 let (lowered, width) = lowered(self, layout)?;
38 let mut pending = Vec::new();
39 let mut args = Vec::with_capacity(lowered.ops.len());
40 for (slot, op) in lowered.ops.iter().enumerate() {
41 args.push(pending.split_off(pending.len() - arity_of(op)));
42 pending.push(slot);
43 }
44 Ok(Program {
45 ops: lowered.ops,
46 widths: lowered.widths,
47 args,
48 formulas: lowered.formulas,
49 indices: lowered.indices,
50 sites: layout.sites.clone(),
51 width,
52 })
53 }
54}
55
56#[derive(Clone)]
57enum State {
58 Filter(FilterSite),
59 Physics(Box<dyn Solver>),
60}
61
62impl Clone for Box<dyn Solver> {
63 fn clone(&self) -> Box<dyn Solver> {
64 self.boxed()
65 }
66}
67
68fn open(p: &Program, grid: Grid) -> Result<Vec<State>, SampleError> {
71 let mut lanes = vec![1usize; p.sites.len()];
72 for (slot, op) in p.ops.iter().enumerate() {
73 if let Op::Filter { site, .. } = op {
74 lanes[site.0 as usize] = p.widths[slot];
75 }
76 }
77 p.sites
78 .iter()
79 .zip(lanes)
80 .map(|(s, width)| {
81 Ok(match s {
82 Site::Filter(shape) => State::Filter(FilterSite::new(
83 *shape,
84 width,
85 &[0.0],
86 &[0.0],
87 &[0.0],
88 grid.sr(),
89 )),
90 Site::Physics(params) => State::Physics(site(params, grid.sr())?),
91 })
92 })
93 .collect()
94}
95
96fn part(v: &[f64], c: usize) -> f64 {
98 v[c.min(v.len() - 1)]
99}
100
101pub struct Machine {
104 program: Program,
105 states: Vec<State>,
106 block: Block,
107 grid: Grid,
108 ahead: Vec<(i64, Program)>,
110}
111
112#[derive(Clone)]
113pub struct MachineState {
114 sites: Vec<Site>,
115 states: Vec<State>,
116}
117
118impl State {
119 fn bytes(&self) -> usize {
120 match self {
121 State::Filter(filter) => filter.bytes(),
122 State::Physics(solver) => solver.bytes(),
123 }
124 }
125}
126
127impl MachineState {
128 pub fn bytes(&self) -> usize {
129 let states: usize = self.states.iter().map(State::bytes).sum();
130 size_of::<Self>() + std::mem::size_of_val(self.sites.as_slice()) + states
131 }
132}
133
134impl Machine {
135 pub fn over(spanned: &Spanned, at: i64) -> Result<Machine, SampleError> {
137 let grid = spanned.grid();
138 let mut ahead: Vec<(i64, Program)> = spanned
139 .compiled()
140 .iter()
141 .filter(|(span, _)| span.to > at)
142 .map(|(span, program)| (span.from, program.clone()))
143 .collect();
144 ahead.reverse();
145 let first = match ahead.pop() {
146 Some((_, program)) => program,
147 None => spanned.silent()?,
148 };
149 let states = open(&first, grid)?;
150 let block = Block::of(&first.widths);
151 Ok(Machine {
152 program: first,
153 states,
154 block,
155 grid,
156 ahead,
157 })
158 }
159
160 pub fn width(&self) -> usize {
161 self.program.width
162 }
163
164 pub fn stateful(&self) -> bool {
165 !self.program.sites.is_empty()
166 }
167
168 pub fn bytes(&self) -> usize {
169 self.states.iter().map(State::bytes).sum()
170 }
171
172 pub fn run_to(&mut self, to: i64, reads: &[Window], own: &mut Tape) -> Result<(), SampleError> {
173 for state in &mut self.states {
174 if let State::Filter(filter) = state {
175 filter.forget_frames();
176 }
177 }
178 self.steps(to, reads, own)
179 }
180
181 pub fn run_on(&mut self, to: i64, reads: &[Window], own: &mut Tape) -> Result<(), SampleError> {
183 self.steps(to, reads, own)
184 }
185
186 fn steps(&mut self, to: i64, reads: &[Window], own: &mut Tape) -> Result<(), SampleError> {
187 loop {
188 while let Some((from, _)) = self.ahead.last()
189 && *from <= own.end()
190 {
191 let (_, program) = self.ahead.pop().expect("a span ahead");
192 self.block = Block::of(&program.widths);
193 self.program = program;
194 }
195 let until = self.ahead.last().map_or(to, |(from, _)| (*from).min(to));
196 self.stepped(until, reads, own)?;
197 if own.end() >= to {
198 return Ok(());
199 }
200 }
201 }
202
203 fn stepped(&mut self, to: i64, reads: &[Window], own: &mut Tape) -> Result<(), SampleError> {
204 let p = &self.program;
205 while own.end() < to {
206 let from = own.end();
207 let len = p.block(from, (to - from).min(BLOCK as i64) as usize);
208 let here = Here {
209 reads,
210 own: own.window(),
211 grid: self.grid,
212 };
213 let (held, refused) =
214 block::run(p, &mut self.block, &here, &mut self.states, (from, len));
215 for i in 0..held {
216 let top = self.block.top(p, i);
217 for c in 0..p.width {
218 own.push(c, part(top, c));
219 }
220 }
221 if let Some(e) = refused {
222 return Err(e);
223 }
224 }
225 Ok(())
226 }
227
228 pub fn solver(&self, site: usize) -> Option<&dyn Solver> {
230 match self.states.get(site)? {
231 State::Physics(solver) => Some(solver.as_ref()),
232 State::Filter(_) => None,
233 }
234 }
235
236 pub fn filter(&self, site: usize) -> Option<&FilterSite> {
237 match self.states.get(site)? {
238 State::Filter(filter) => Some(filter),
239 State::Physics(_) => None,
240 }
241 }
242
243 pub fn state(&self) -> MachineState {
244 MachineState {
245 sites: self.program.sites.clone(),
246 states: self.states.clone(),
247 }
248 }
249
250 pub fn restart(&mut self) {
251 self.states = open(&self.program, self.grid).expect("the sites opened once already");
252 }
253
254 pub fn accepts(&self, held: &MachineState) -> bool {
256 held.sites == self.program.sites
257 }
258
259 pub fn carry(&mut self, held: &MachineState) -> bool {
261 let taken = self.accepts(held);
262 if taken {
263 self.states.clone_from(&held.states);
264 }
265 taken
266 }
267}
268
269impl Program {
270 fn block(&self, from: i64, most: usize) -> usize {
272 let mut len = most;
273 for op in &self.ops {
274 match op {
275 Op::Read {
276 slot: Slot::Own,
277 at,
278 }
279 | Op::ReadScaled {
280 slot: Slot::Own,
281 at,
282 ..
283 } => {
284 let last = |len: usize| from + len as i64 - 1;
285 while len > 1 && at.at(from).max(at.at(last(len))) >= from {
286 len /= 2;
287 }
288 }
289 Op::Indexed {
290 slot: Slot::Own,
291 reach,
292 ..
293 } => {
294 len = match reach {
295 Some((_, most)) if *most < 0 => len.min(most.unsigned_abs() as usize),
296 _ => 1,
297 }
298 }
299 _ => {}
300 }
301 }
302 len.max(1)
303 }
304}
305
306fn arity_of(op: &Op) -> usize {
307 match op {
308 Op::Const(_)
309 | Op::Time
310 | Op::Wrap(_)
311 | Op::Noise { .. }
312 | Op::Read { .. }
313 | Op::ReadScaled { .. } => 0,
314 Op::Physics { arity, .. } => *arity,
315 Op::Map(_) | Op::Crop { .. } | Op::Channel(_) | Op::Formula { .. } => 1,
316 Op::Indexed { arity, .. } | Op::Instant { arity, .. } => *arity,
317 Op::Sub | Op::Div | Op::Pow | Op::Zip(_) => 2,
318 Op::Add(n) | Op::Mul(n) | Op::Join(n) => *n,
319 Op::Filter { .. } => 4,
320 }
321}