#![cfg_attr(not(test), no_std)]
use core::fmt;
use core::mem;
#[derive(Debug, Clone)]
pub struct Generations<Model> {
current: Model,
scratch: Model,
}
impl<Model> Generations<Model> {
#[inline]
#[must_use]
pub fn new(seed: Model, scratch: Model) -> Self {
Generations {
current: seed,
scratch,
}
}
#[inline]
#[must_use]
pub fn current(&self) -> &Model {
&self.current
}
#[inline]
pub fn step(&mut self, stepper: impl FnOnce(&Model, &mut Model)) -> &Model {
stepper(&self.current, &mut self.scratch);
mem::swap(&mut self.current, &mut self.scratch);
&self.scratch
}
#[inline]
pub fn reset_with(&mut self, seeder: impl FnOnce(&mut Model)) {
seeder(&mut self.current)
}
#[inline]
pub fn reset(&mut self, seed: Model) {
self.current = seed;
}
#[inline]
#[must_use]
pub fn with_rule<F: FnMut(&Model, &mut Model)>(self, stepper: F) -> Simulation<Model, F> {
Simulation {
generations: self,
stepper,
}
}
}
impl<Model: Clone> Generations<Model> {
#[inline]
#[must_use]
pub fn new_cloned(seed_generation: Model) -> Self {
let scratch = seed_generation.clone();
Self::new(seed_generation, scratch)
}
#[inline]
pub fn reset_from(&mut self, seed: &Model) {
self.current.clone_from(seed)
}
}
impl<Model: Default> Generations<Model> {
#[inline]
#[must_use]
pub fn new_defaulted(seed_generation: Model) -> Self {
Self::new(seed_generation, Model::default())
}
}
#[derive(Clone)]
pub struct Simulation<Model, Step> {
generations: Generations<Model>,
stepper: Step,
}
impl<Model, Step> Simulation<Model, Step> {
#[inline]
#[must_use]
pub fn current(&self) -> &Model {
self.generations.current()
}
#[inline]
pub fn reset_with(&mut self, seeder: impl FnOnce(&mut Model)) {
self.generations.reset_with(seeder)
}
#[inline]
pub fn reset(&mut self, seed: Model) {
self.generations.reset(seed)
}
#[inline]
pub fn unwrap(self) -> Generations<Model> {
self.generations
}
}
impl<Model: Clone, Step> Simulation<Model, Step> {
#[inline]
pub fn reset_from(&mut self, seed: &Model) {
self.generations.reset_from(seed)
}
}
impl<Model, Step: FnMut(&Model, &mut Model)> Simulation<Model, Step> {
#[inline]
pub fn step(&mut self) -> &Model {
self.generations.step(&mut self.stepper)
}
}
impl<Model: fmt::Debug, Step> fmt::Debug for Simulation<Model, Step> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Simulation")
.field("generations", &self.generations)
.field("stepper", &"<closure>")
.finish()
}
}
impl<Model, Step> AsRef<Generations<Model>> for Simulation<Model, Step> {
fn as_ref(&self) -> &Generations<Model> {
&self.generations
}
}
#[cfg(test)]
mod tests {
use crate::Generations;
#[test]
fn basic_test() {
let gen = Generations::new(vec![0, 1, 0, 1, 1, -1, -1, 0], vec![]);
let mut gen = gen.with_rule(|current_gen, next_gen| {
next_gen.clear();
next_gen.push(0);
for window in current_gen.windows(3) {
next_gen.push(window[0] + window[1] + window[2]);
}
next_gen.push(0);
});
assert_eq!(gen.current(), &[0, 1, 0, 1, 1, -1, -1, 0]);
gen.step();
assert_eq!(gen.current(), &[0, 1, 2, 2, 1, -1, -2, 0]);
gen.step();
assert_eq!(gen.current(), &[0, 3, 5, 5, 2, -2, -3, 0]);
gen.step();
assert_eq!(gen.current(), &[0, 8, 13, 12, 5, -3, -5, 0]);
gen.step();
assert_eq!(gen.current(), &[0, 21, 33, 30, 14, -3, -8, 0]);
}
#[test]
fn debug_print_test() {
let thing = Generations::new_defaulted(vec![0]).with_rule(|_c, _n| {});
format!("{:?}", &thing);
}
}