From 1c49bf92c844e28c4ae593634f0f0bebce77c341 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Sat, 4 Mar 2023 12:53:12 +0000 Subject: [PATCH] Add N-dimensional position code --- src/main.rs | 2 + src/system/mod.rs | 1 + src/system/nd.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/system/nd.rs diff --git a/src/main.rs b/src/main.rs index 521569f..8b2a1c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![feature(array_zip)] + use std::path::PathBuf; use rand::prelude::*; diff --git a/src/system/mod.rs b/src/system/mod.rs index 39dacd9..1da8f5f 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -6,6 +6,7 @@ use serde::{Serialize, Deserialize, Serializer}; pub mod walker; pub mod storage; pub mod model; +pub mod nd; pub trait GriddedPosition: Add + Serialize + Clone { fn zero() -> Self; diff --git a/src/system/nd.rs b/src/system/nd.rs new file mode 100644 index 0000000..a21e223 --- /dev/null +++ b/src/system/nd.rs @@ -0,0 +1,99 @@ +use std::ops::Add; +use rand::Rng; +use serde::{Serialize, Serializer}; +use serde::ser::SerializeMap; +use crate::system::GriddedPosition; +use crate::system::storage::Storage; + +pub struct NDVectorStorage { + backing: Vec, + grid_size: u32, +} + +impl Storage> for NDVectorStorage { + fn at(&self, position: &NDPosition) -> bool { + return self.backing[position.linear_index(self.grid_size)]; + } + + fn deposit(&mut self, position: &NDPosition) { + self.backing[position.linear_index(self.grid_size)] = true; + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct NDPosition([i32; DIM]); + +impl NDPosition { + pub fn in_direction(direction: usize, value: i32) -> Self { + let mut arr = [0; DIM]; + arr[direction] = value; + NDPosition(arr) + } +} + +impl Add for NDPosition { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0.zip(rhs.0).map(|(a, b)| a + b)) + } +} + +impl Serialize for NDPosition { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + let mut map = serializer.serialize_map(Some(DIM))?; + for (i, v) in self.0.iter().enumerate() { + map.serialize_entry(&format!("r{}", i), v)?; + } + map.end() + } +} + +impl GriddedPosition for NDPosition { + fn zero() -> Self { + NDPosition([0; DIM]) + } + + fn spawn(rng: &mut R, radius: f32) -> Self { + let mut a: [f32; DIM] = [0f32; DIM]; + let mut b: [i32; DIM] = [0i32; DIM]; + + for i in 0..DIM { + a[i] = rng.gen_range(0f32..1f32); + } + + let norm = a.iter().sum::() + .sqrt(); + + for i in 0..DIM { + a[i] = a[i] / norm; + b[i] = a[i] as i32; + } + + return Self(b) + } + + fn abs(&self) -> f32 { + let a: i32 = self.0.iter() + .map(|r| r.pow(2)) + .sum(); + + (a as f32).powf(0.5) + } + + fn neighbours(&self) -> Vec { + let a = (0..DIM).into_iter(); + + return a.flat_map(|direction| [ + self.clone() + NDPosition::in_direction(direction, 1), + self.clone() + NDPosition::in_direction(direction, -1), + ]).collect(); + } + + fn linear_index(&self, grid_size: u32) -> usize { + self.0.iter() + .enumerate() + .map(|(i, v)| (grid_size.pow(i as u32) as usize) * (v + ((grid_size / 2) as i32)) as usize) + .sum() + } +}