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::f32::consts::PI;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use num_integer::Integer;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Serialize, Deserialize, Serializer};
|
use serde::{Serialize, Deserialize, Serializer};
|
||||||
|
|
||||||
@ -9,10 +10,12 @@ pub mod model;
|
|||||||
pub mod nd;
|
pub mod nd;
|
||||||
|
|
||||||
pub trait GriddedPosition: Add<Output=Self> + Serialize + Clone {
|
pub trait GriddedPosition: Add<Output=Self> + Serialize + Clone {
|
||||||
|
const NEIGHBOURS: u32;
|
||||||
|
|
||||||
fn zero() -> Self;
|
fn zero() -> Self;
|
||||||
fn spawn<R: Rng>(rng: &mut R, radius: f32) -> Self;
|
fn spawn<R: Rng>(rng: &mut R, radius: f32) -> Self;
|
||||||
fn abs(&self) -> f32;
|
fn abs(&self) -> f32;
|
||||||
fn neighbours(&self) -> Vec<Self>;
|
fn neighbour(&self, neighbour_index: u32) -> Self;
|
||||||
fn linear_index(&self, grid_size: u32) -> usize;
|
fn linear_index(&self, grid_size: u32) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +40,8 @@ impl Add for Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GriddedPosition for Position {
|
impl GriddedPosition for Position {
|
||||||
|
const NEIGHBOURS: u32 = 4;
|
||||||
|
|
||||||
fn zero() -> Position {
|
fn zero() -> Position {
|
||||||
Position { x: 0, y: 0 }
|
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)
|
((self.x.pow(2) + self.y.pow(2)) as f32).powf(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn neighbours(&self) -> Vec<Self> {
|
fn neighbour(&self, neighbour_index: u32) -> Self {
|
||||||
let a = (0..2).into_iter();
|
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() + offset
|
||||||
self.clone() + Position::in_direction(direction, 1),
|
|
||||||
self.clone() + Position::in_direction(direction, -1),
|
|
||||||
]).collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn linear_index(&self, grid_size: u32) -> usize {
|
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 {
|
fn check_stick(&mut self, position: &P) -> bool {
|
||||||
position.neighbours()
|
(0..P::NEIGHBOURS)
|
||||||
.iter()
|
.map(|n| position.neighbour(n))
|
||||||
.any(|neighbour|
|
.any(|neighbour|
|
||||||
self.space.at(&neighbour)
|
self.space.at(&neighbour)
|
||||||
&& self.rng.gen_range(0.0f32..=1.0) < self.stick_probability
|
&& self.rng.gen_range(0.0f32..=1.0) < self.stick_probability
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use num_integer::Integer;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
use serde::ser::SerializeMap;
|
use serde::ser::SerializeMap;
|
||||||
@ -56,6 +57,8 @@ impl<const DIM: usize> Serialize for NDPosition<DIM> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
||||||
|
const NEIGHBOURS: u32 = { 2u32.pow(DIM as u32) } as u32;
|
||||||
|
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
NDPosition([0; DIM])
|
NDPosition([0; DIM])
|
||||||
}
|
}
|
||||||
@ -87,13 +90,12 @@ impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
|||||||
(a as f32).powf(0.5)
|
(a as f32).powf(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn neighbours(&self) -> Vec<Self> {
|
fn neighbour(&self, neighbour_index: u32) -> Self {
|
||||||
let a = (0..DIM).into_iter();
|
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() + offset
|
||||||
self.clone() + NDPosition::in_direction(direction, 1),
|
|
||||||
self.clone() + NDPosition::in_direction(direction, -1),
|
|
||||||
]).collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn linear_index(&self, grid_size: u32) -> usize {
|
fn linear_index(&self, grid_size: u32) -> usize {
|
||||||
|
|||||||
@ -10,9 +10,7 @@ pub struct LocalRandomWalker;
|
|||||||
|
|
||||||
impl<Position: GriddedPosition> Walker<Position> for LocalRandomWalker {
|
impl<Position: GriddedPosition> Walker<Position> for LocalRandomWalker {
|
||||||
fn walk<R: Rng>(&self, rng: &mut R, position: &Position) -> Position {
|
fn walk<R: Rng>(&self, rng: &mut R, position: &Position) -> Position {
|
||||||
let neighbours = position.neighbours();
|
position.neighbour(rng.gen_range(0u32..Position::NEIGHBOURS))
|
||||||
let index = rng.gen_range(0..(neighbours.len()));
|
|
||||||
neighbours[index].clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user