1use handwired_rs::TensorExecutor;
9use handwired_rs::dsl::Params;
10use handwired_rs::handwired;
11
12const N: usize = 24;
13
14#[handwired]
15fn life_step(grid: [[bool; 24]; 24]) -> [[bool; 24]; 24] {
16 let mut next: [[bool; 24]; 24] = [[false; 24]; 24];
17 for row in 0..24 {
18 for column in 0..24 {
19 let mut neighbors: u8 = 0;
20 for dr in 0..3 {
21 for dc in 0..3 {
22 if dr != 1 || dc != 1 {
23 neighbors += grid[(row + dr + 23) % 24][(column + dc + 23) % 24] as u8;
25 }
26 }
27 }
28 next[row][column] = neighbors == 3 || (grid[row][column] && neighbors == 2);
29 }
30 }
31 next
32}
33
34fn main() {
35 let compiled = life_step_circuit();
36 let report = compiled.verify(200).unwrap();
37 eprintln!(
38 "life_step: {} live operations in {} layers; verified on {} random grids",
39 compiled.program.live_operation_count(),
40 compiled.program.layers.len(),
41 report.checked
42 );
43 let mut grid = [[false; N]; N];
45 for (row, column) in [(1, 2), (2, 3), (3, 1), (3, 2), (3, 3)] {
46 grid[row][column] = true;
47 }
48 for (row, column) in [(14, 4), (15, 5), (16, 3), (16, 4), (16, 5)] {
49 grid[row][column] = true;
50 }
51 for (row, column) in [(4, 14), (4, 17), (5, 18), (6, 14), (6, 18), (7, 15), (7, 16), (7, 17), (7, 18)] {
52 grid[row][column] = true;
53 }
54 for (row, column) in [(16, 16), (16, 17), (17, 15), (17, 16), (18, 16)] {
55 grid[row][column] = true;
56 }
57 let mut executor = TensorExecutor::new(&compiled.program);
58 let mut source = Vec::new();
59 for generation in 0..120 {
60 println!(
61 "{}",
62 grid.iter().flat_map(|row| row.iter().map(|&alive| if alive { '#' } else { '.' })).collect::<String>()
63 );
64 source.clear();
65 (grid,).encode(&mut source);
66 let outputs = executor.run(&source);
67 let next: [[bool; N]; N] =
68 std::array::from_fn(|row| std::array::from_fn(|column| outputs[row * N + column] == 1.0));
69 assert_eq!(next, life_step(grid), "generation {generation}: the circuit disagrees with life_step()");
70 grid = next;
71 }
72}