use a more compact memory rep

This commit is contained in:
histausse 2021-05-14 00:13:46 +02:00
parent 40c026f32a
commit 50f94820a5
Signed by: histausse
GPG key ID: 67486F107F62E9E9
3 changed files with 38 additions and 45 deletions

View file

@ -11,6 +11,7 @@ crate-type = ["cdylib", "rlib"]
default = ["console_error_panic_hook"] default = ["console_error_panic_hook"]
[dependencies] [dependencies]
fixedbitset = "0.4.0"
js-sys = "0.3" js-sys = "0.3"
wasm-bindgen = "0.2.63" wasm-bindgen = "0.2.63"

View file

@ -1,9 +1,12 @@
mod utils; mod utils;
extern crate js_sys;
extern crate fixedbitset;
use std::fmt; use std::fmt;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use fixedbitset::FixedBitSet;
extern crate js_sys;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator. // allocator.
@ -21,19 +24,11 @@ pub fn greet(name: &str) {
alert(&format!("Hello, {name}!", name=name)) alert(&format!("Hello, {name}!", name=name))
} }
#[wasm_bindgen]
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cell {
Dead = 0,
Alive = 1,
}
#[wasm_bindgen] #[wasm_bindgen]
pub struct Universe { pub struct Universe {
width: u32, width: u32,
height: u32, height: u32,
cells: Vec<Cell>, cells: FixedBitSet,
} }
impl Universe{ impl Universe{
@ -69,14 +64,13 @@ impl Universe {
let i = self.get_index(row, col); let i = self.get_index(row, col);
let cell = self.cells[i]; let cell = self.cells[i];
let live_neighbor = self.live_neighbor_count(row, col); let live_neighbor = self.live_neighbor_count(row, col);
let next_cell = match (cell, live_neighbor){ next.set(i, match (cell, live_neighbor){
(Cell::Alive, x) if x < 2 => Cell::Dead, (true, x) if x < 2 => false,
(Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive, (true, 2) | (true, 3) => true,
(Cell::Alive, x) if x > 3 => Cell::Dead, (true, x) if x > 3 => false,
(Cell::Dead, 3) => Cell::Alive, (false, 3) => true,
(other, _) => other, (other, _) => other,
}; });
next[i] = next_cell;
} }
} }
self.cells = next; self.cells = next;
@ -85,16 +79,13 @@ impl Universe {
pub fn new() -> Universe { pub fn new() -> Universe {
let width = 64; let width = 64;
let height = 64; let height = 64;
let size = (width * height) as usize;
let cells = (0..width * height) let mut cells = FixedBitSet::with_capacity(size);
.map(|i| {
if i % 2 == 0 || i % 7 == 0 { for i in 0..size {
Cell::Alive cells.set(i, i % 2 == 0 || i % 7 == 0);
} else { }
Cell::Dead
}
})
.collect();
Universe { Universe {
width, width,
@ -106,16 +97,13 @@ impl Universe {
pub fn new_random() -> Universe { pub fn new_random() -> Universe {
let width = 64; let width = 64;
let height = 64; let height = 64;
let size = (width * height) as usize;
let cells = (0..width * height) let mut cells = FixedBitSet::with_capacity(size);
.map(|_i| {
if js_sys::Math::random() < 0.5 { for i in 0..size {
Cell::Alive cells.set(i, js_sys::Math::random() < 0.5);
} else { }
Cell::Dead
}
})
.collect();
Universe { Universe {
width, width,
@ -127,16 +115,19 @@ impl Universe {
pub fn new_space_ship() -> Universe { pub fn new_space_ship() -> Universe {
let width : u32 = 64; let width : u32 = 64;
let height : u32 = 64; let height : u32 = 64;
let size = (width * height) as usize;
let mut cells : Vec<Cell> = (0..width * height) let mut cells = FixedBitSet::with_capacity(size);
.map(|_i| { Cell::Dead })
.collect(); for i in 0..size {
cells.set(i, false);
}
let x0 = 32; let x0 = 32;
let y0 = 32; let y0 = 32;
for (x, y) in [(0, 2), (1, 0), (1, 2), (2, 1), (2, 2)].iter().cloned() { for (x, y) in [(0, 2), (1, 0), (1, 2), (2, 1), (2, 2)].iter().cloned() {
let i = ((y0 + y) * width + x0 + x) as usize; let i = ((y0 + y) * width + x0 + x) as usize;
cells[i] = Cell::Alive; cells.set(i, true);
} }
Universe { Universe {
@ -158,16 +149,17 @@ impl Universe {
self.height self.height
} }
pub fn cells(&self) -> *const Cell { pub fn cells(&self) -> *const u32 {
self.cells.as_ptr() self.cells.as_slice().as_ptr()
} }
} }
impl fmt::Display for Universe { impl fmt::Display for Universe {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for line in self.cells.as_slice().chunks(self.width as usize) { for row in 0..self.height {
for &cell in line { for col in 0..self.width {
let symbole = if cell == Cell::Dead { '◻' } else { '◼' }; let i = self.get_index(row, col);
let symbole = if self.cells[i] { '◻' } else { '◼' };
write!(f, "{}", symbole)?; write!(f, "{}", symbole)?;
} }
write!(f, "\n")?; write!(f, "\n")?;

2
www

@ -1 +1 @@
Subproject commit b0799ea316d590cd432fee5f53914287e2a328d6 Subproject commit f6fa2759a6dce5379554d7294f00487bb1565004