Halve run-time by swapping to index based neighbours to avoid need for allocating Vecs
This commit is contained in:
parent
f0e862616d
commit
973bcf0381
@ -1,5 +1,6 @@
|
||||
use std::f32::consts::PI;
|
||||
use std::ops::Add;
|
||||
use num_integer::Integer;
|
||||
use rand::Rng;
|
||||
use serde::{Serialize, Deserialize, Serializer};
|
||||
|
||||
@ -9,10 +10,12 @@ pub mod model;
|
||||
pub mod nd;
|
||||
|
||||
pub trait GriddedPosition: Add<Output=Self> + Serialize + Clone {
|
||||
const NEIGHBOURS: u32;
|
||||
|
||||
fn zero() -> Self;
|
||||
fn spawn<R: Rng>(rng: &mut R, radius: f32) -> Self;
|
||||
fn abs(&self) -> f32;
|
||||
fn neighbours(&self) -> Vec<Self>;
|
||||
fn neighbour(&self, neighbour_index: u32) -> Self;
|
||||
fn linear_index(&self, grid_size: u32) -> usize;
|
||||
}
|
||||
|
||||
@ -37,6 +40,8 @@ impl Add for Position {
|
||||
}
|
||||
|
||||
impl GriddedPosition for Position {
|
||||
const NEIGHBOURS: u32 = 4;
|
||||
|
||||
fn zero() -> Position {
|
||||
Position { x: 0, y: 0 }
|
||||
}
|
||||
@ -51,13 +56,12 @@ impl GriddedPosition for Position {
|
||||
((self.x.pow(2) + self.y.pow(2)) as f32).powf(0.5)
|
||||
}
|
||||
|
||||
fn neighbours(&self) -> Vec<Self> {
|
||||
let a = (0..2).into_iter();
|
||||
fn neighbour(&self, neighbour_index: u32) -> Self {
|
||||
let (dim, sign) = neighbour_index.div_rem(&2);
|
||||
let sign = if sign == 0 { 1 } else { -1 };
|
||||
let offset = Position::in_direction(dim, sign);
|
||||
|
||||
return a.flat_map(|direction| [
|
||||
self.clone() + Position::in_direction(direction, 1),
|
||||
self.clone() + Position::in_direction(direction, -1),
|
||||
]).collect();
|
||||
self.clone() + offset
|
||||
}
|
||||
|
||||
fn linear_index(&self, grid_size: u32) -> usize {
|
||||
|
||||
@ -114,8 +114,8 @@ impl<R: Rng, P: GriddedPosition, S: Storage<P>, W: Walker<P>> DLASystem<R, P, S,
|
||||
}
|
||||
|
||||
fn check_stick(&mut self, position: &P) -> bool {
|
||||
position.neighbours()
|
||||
.iter()
|
||||
(0..P::NEIGHBOURS)
|
||||
.map(|n| position.neighbour(n))
|
||||
.any(|neighbour|
|
||||
self.space.at(&neighbour)
|
||||
&& self.rng.gen_range(0.0f32..=1.0) < self.stick_probability
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use std::ops::Add;
|
||||
use num_integer::Integer;
|
||||
use rand::Rng;
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::ser::SerializeMap;
|
||||
@ -56,6 +57,8 @@ impl<const DIM: usize> Serialize for NDPosition<DIM> {
|
||||
}
|
||||
|
||||
impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
||||
const NEIGHBOURS: u32 = { 2u32.pow(DIM as u32) } as u32;
|
||||
|
||||
fn zero() -> Self {
|
||||
NDPosition([0; DIM])
|
||||
}
|
||||
@ -87,13 +90,12 @@ impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
||||
(a as f32).powf(0.5)
|
||||
}
|
||||
|
||||
fn neighbours(&self) -> Vec<Self> {
|
||||
let a = (0..DIM).into_iter();
|
||||
fn neighbour(&self, neighbour_index: u32) -> Self {
|
||||
let (dim, sign) = neighbour_index.div_rem(&(DIM as u32));
|
||||
let sign = if sign == 0 { 1 } else { -1 };
|
||||
let offset = Self::in_direction(dim as usize, sign);
|
||||
|
||||
return a.flat_map(|direction| [
|
||||
self.clone() + NDPosition::in_direction(direction, 1),
|
||||
self.clone() + NDPosition::in_direction(direction, -1),
|
||||
]).collect();
|
||||
self.clone() + offset
|
||||
}
|
||||
|
||||
fn linear_index(&self, grid_size: u32) -> usize {
|
||||
|
||||
@ -10,9 +10,7 @@ pub struct LocalRandomWalker;
|
||||
|
||||
impl<Position: GriddedPosition> Walker<Position> for LocalRandomWalker {
|
||||
fn walk<R: Rng>(&self, rng: &mut R, position: &Position) -> Position {
|
||||
let neighbours = position.neighbours();
|
||||
let index = rng.gen_range(0..(neighbours.len()));
|
||||
neighbours[index].clone()
|
||||
position.neighbour(rng.gen_range(0u32..Position::NEIGHBOURS))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user