init
This commit is contained in:
commit
47ff50be5f
6 changed files with 304 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gol-bitwise"
|
||||||
|
version = "0.1.0"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "gol-bitwise"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
hard_tabs = true
|
125
src/main.rs
Normal file
125
src/main.rs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
mod tile;
|
||||||
|
use tile::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut tile = EMPTY_TILE;
|
||||||
|
let mut tile2 = EMPTY_TILE;
|
||||||
|
let mut tile3 = EMPTY_TILE;
|
||||||
|
let mut tile4 = EMPTY_TILE;
|
||||||
|
// tile[WIDTH - 8] = (0b_1111_1111_1100_0000 as Row).reverse_bits();
|
||||||
|
tile[WIDTH - 8] = 0b_00100000;
|
||||||
|
tile[WIDTH - 7] = 0b_00010000;
|
||||||
|
tile[WIDTH - 6] = 0b_01110000;
|
||||||
|
|
||||||
|
tile[WIDTH - 3] = 0b_0010;
|
||||||
|
tile[WIDTH - 2] = 0b_0001;
|
||||||
|
tile[WIDTH - 1] = 0b_0111;
|
||||||
|
loop {
|
||||||
|
let edges = Edges::full(
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile3,
|
||||||
|
&tile2,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile4,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
);
|
||||||
|
let edges2 = Edges::full(
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile4,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile3,
|
||||||
|
);
|
||||||
|
let edges3 = Edges::full(
|
||||||
|
&tile,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile4,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile2,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
);
|
||||||
|
let edges4 = Edges::full(
|
||||||
|
&tile2,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile3,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&tile,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
&EMPTY_TILE,
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
println!("\n{:#<w$}", "", w = WIDTH * 2 + 1);
|
||||||
|
print_tiles(&tile, &tile2);
|
||||||
|
// print_tile(&tile3);
|
||||||
|
println!("{:-<w$}", "", w = WIDTH * 2 + 1);
|
||||||
|
print_tiles(&tile3, &tile4);
|
||||||
|
// print_tile(&tile2);
|
||||||
|
// print_tile(&tile4);
|
||||||
|
|
||||||
|
step(&mut tile, &edges);
|
||||||
|
step(&mut tile2, &edges2);
|
||||||
|
step(&mut tile3, &edges3);
|
||||||
|
step(&mut tile4, &edges4);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut a = String::new();
|
||||||
|
std::io::stdin().read_line(&mut a).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn print_tile(tile: &Tile) {
|
||||||
|
// for y in 0..(WIDTH / 2) {
|
||||||
|
// let top = tile[y * 2];
|
||||||
|
// let bot = tile[y * 2 + 1];
|
||||||
|
// let mut row = String::with_capacity(WIDTH);
|
||||||
|
// for bit in (0..WIDTH).rev() {
|
||||||
|
// let states = ((top >> bit) & 1, (bot >> bit) & 1);
|
||||||
|
// row.push(match states {
|
||||||
|
// (0, 0) => ' ',
|
||||||
|
// (1, 0) => '▀',
|
||||||
|
// (0, 1) => '▄',
|
||||||
|
// (1, 1) => '█',
|
||||||
|
// _ => unreachable!(),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// println!("{row}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn blocks(top: Row, bottom: Row, bit: usize) -> char {
|
||||||
|
let states = ((top >> bit) & 1, (bottom >> bit) & 1);
|
||||||
|
match states {
|
||||||
|
(0, 0) => ' ',
|
||||||
|
(1, 0) => '▀',
|
||||||
|
(0, 1) => '▄',
|
||||||
|
(1, 1) => '█',
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_tiles(left: &TileArr, right: &TileArr) {
|
||||||
|
for y in 0..(WIDTH / 2) {
|
||||||
|
let a = left[y * 2];
|
||||||
|
let b = left[y * 2 + 1];
|
||||||
|
let mut row = String::with_capacity(WIDTH * 2 + 1);
|
||||||
|
for bit in (0..WIDTH).rev() {
|
||||||
|
row.push(blocks(a, b, bit));
|
||||||
|
}
|
||||||
|
row.push('|');
|
||||||
|
let a = right[y * 2];
|
||||||
|
let b = right[y * 2 + 1];
|
||||||
|
for bit in (0..WIDTH).rev() {
|
||||||
|
row.push(blocks(a, b, bit));
|
||||||
|
}
|
||||||
|
println!("{row}");
|
||||||
|
}
|
||||||
|
}
|
162
src/tile.rs
Normal file
162
src/tile.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
pub type Row = u32;
|
||||||
|
pub type TileArr = [Row; WIDTH];
|
||||||
|
pub const EMPTY_TILE: TileArr = [0; WIDTH];
|
||||||
|
|
||||||
|
pub const WIDTH: usize = Row::BITS as usize;
|
||||||
|
const LAST: usize = WIDTH - 1;
|
||||||
|
|
||||||
|
pub struct Edges {
|
||||||
|
n: Row,
|
||||||
|
s: Row,
|
||||||
|
e: Row,
|
||||||
|
w: Row,
|
||||||
|
nw: bool,
|
||||||
|
ne: bool,
|
||||||
|
sw: bool,
|
||||||
|
se: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(tile: &mut TileArr, edges: &Edges) {
|
||||||
|
fn step_row(state: &mut Row, a0: Row, a1: Row, b0: Row, b1: Row, c0: Row, c1: Row) {
|
||||||
|
// simulates addition of [WIDTH] groups of 3 2-bit numbers using bitwise operations
|
||||||
|
|
||||||
|
// partial sum (first and second number/row)
|
||||||
|
let t0 = a0 ^ b0;
|
||||||
|
let t1 = (a0 & b0) ^ (a1 ^ b1);
|
||||||
|
let t2 = (a0 & b0 & (a1 ^ b1)) | (a1 & b1);
|
||||||
|
|
||||||
|
// total neighbor count (incl. center cell)
|
||||||
|
let n0 = t0 ^ c0;
|
||||||
|
let n1 = (t0 & c0) ^ (t1 ^ c1);
|
||||||
|
let n2 = t2 ^ ((t0 & c0 & (t1 ^ c1)) | (t1 & c1));
|
||||||
|
|
||||||
|
// count == 3 || (old_state && count == 4)
|
||||||
|
*state = (!n2 & n1 & n0) | (*state & n2 & !(n0 | n1));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut partial_sums_1 = EMPTY_TILE;
|
||||||
|
let mut partial_sums_2 = EMPTY_TILE;
|
||||||
|
|
||||||
|
for (y, row) in tile.iter().enumerate() {
|
||||||
|
let left = (row >> 1) | edges.west_bit(y);
|
||||||
|
let right = (row << 1) | edges.east_bit(y);
|
||||||
|
partial_sums_1[y] = row ^ left ^ right;
|
||||||
|
partial_sums_2[y] = (left & right) | ((left ^ right) & row);
|
||||||
|
}
|
||||||
|
|
||||||
|
for y in 1..LAST {
|
||||||
|
step_row(
|
||||||
|
&mut tile[y],
|
||||||
|
partial_sums_1[y - 1],
|
||||||
|
partial_sums_2[y - 1],
|
||||||
|
partial_sums_1[y],
|
||||||
|
partial_sums_2[y],
|
||||||
|
partial_sums_1[y + 1],
|
||||||
|
partial_sums_2[y + 1],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// top and bottom cases
|
||||||
|
let (partial_north_1, partial_north_2) = {
|
||||||
|
let row = edges.n;
|
||||||
|
let left = (row >> 1) | edges.nw_bit();
|
||||||
|
let right = (row << 1) | edges.ne_bit();
|
||||||
|
(row ^ left ^ right, (left & right) | ((left ^ right) & row))
|
||||||
|
};
|
||||||
|
step_row(
|
||||||
|
&mut tile[0],
|
||||||
|
partial_north_1,
|
||||||
|
partial_north_2,
|
||||||
|
partial_sums_1[0],
|
||||||
|
partial_sums_2[0],
|
||||||
|
partial_sums_1[1],
|
||||||
|
partial_sums_2[1],
|
||||||
|
);
|
||||||
|
let (partial_south_1, partial_south_2) = {
|
||||||
|
let row = edges.s;
|
||||||
|
let left = (row >> 1) | edges.sw_bit();
|
||||||
|
let right = (row << 1) | edges.se_bit();
|
||||||
|
(row ^ left ^ right, (left & right) | ((left ^ right) & row))
|
||||||
|
};
|
||||||
|
step_row(
|
||||||
|
&mut tile[LAST],
|
||||||
|
partial_sums_1[WIDTH - 2],
|
||||||
|
partial_sums_2[WIDTH - 2],
|
||||||
|
partial_sums_1[LAST],
|
||||||
|
partial_sums_2[LAST],
|
||||||
|
partial_south_1,
|
||||||
|
partial_south_2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Edges {
|
||||||
|
// pub const EMPTY: Self = Edges {
|
||||||
|
// n: 0,
|
||||||
|
// s: 0,
|
||||||
|
// e: 0,
|
||||||
|
// w: 0,
|
||||||
|
// ne: false,
|
||||||
|
// nw: false,
|
||||||
|
// se: false,
|
||||||
|
// sw: false,
|
||||||
|
// };
|
||||||
|
|
||||||
|
pub fn full(
|
||||||
|
n: &TileArr,
|
||||||
|
s: &TileArr,
|
||||||
|
e: &TileArr,
|
||||||
|
w: &TileArr,
|
||||||
|
ne: &TileArr,
|
||||||
|
nw: &TileArr,
|
||||||
|
se: &TileArr,
|
||||||
|
sw: &TileArr,
|
||||||
|
) -> Self {
|
||||||
|
let mut east = 0;
|
||||||
|
let mut west = 0;
|
||||||
|
for n in 0..WIDTH {
|
||||||
|
east |= (e[n] >> LAST) << n;
|
||||||
|
west |= (w[n] & 1) << n;
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
n: n[LAST],
|
||||||
|
s: s[0],
|
||||||
|
e: east,
|
||||||
|
w: west,
|
||||||
|
nw: (nw[LAST] & 1) != 0,
|
||||||
|
ne: (ne[LAST] >> LAST) != 0,
|
||||||
|
sw: (sw[0] & 1) != 0,
|
||||||
|
se: (se[0] >> LAST) != 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn west_bit(&self, y: usize) -> Row {
|
||||||
|
((self.w >> y) & 1) << LAST
|
||||||
|
}
|
||||||
|
|
||||||
|
fn east_bit(&self, y: usize) -> Row {
|
||||||
|
(self.e >> y) & 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nw_bit(&self) -> Row {
|
||||||
|
if self.nw {
|
||||||
|
1 << LAST
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sw_bit(&self) -> Row {
|
||||||
|
if self.sw {
|
||||||
|
1 << LAST
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ne_bit(&self) -> Row {
|
||||||
|
self.ne as Row
|
||||||
|
}
|
||||||
|
fn se_bit(&self) -> Row {
|
||||||
|
self.se as Row
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue