Add clib to allow for behaviour testing within c-codebase
This commit is contained in:
+89
@@ -0,0 +1,89 @@
|
||||
use crate::system::Position;
|
||||
use crate::system::storage::{Storage, VectorStorage};
|
||||
|
||||
mod system;
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct CPosition(i32, i32);
|
||||
|
||||
pub struct CStorage(VectorStorage);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_new(grid_size: u32) -> &'static mut CStorage {
|
||||
let mut pntr = Box::new(CStorage(VectorStorage::new(grid_size, 2)));
|
||||
Box::leak(pntr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_at(storage: &CStorage, i: i32, j: i32) -> bool {
|
||||
storage.0.at(&Position(i, j))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn storage_deposit(storage: &mut CStorage, i: i32, j: i32, val: u8) {
|
||||
storage.0.write(&Position(i, j), val == 1);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn walk(d: u32, i: i32, j: i32) -> CPosition {
|
||||
return test::b(d, i, j);
|
||||
|
||||
// match d {
|
||||
// 0 => CPosition(i + 1, j),
|
||||
// 1 => CPosition(i - 1, j),
|
||||
// 2 => CPosition(i, j + 1),
|
||||
// 3 => CPosition(i, j - 1),
|
||||
// _ => panic!("Ahh"),
|
||||
// }
|
||||
|
||||
// let (dim, sign) = d.div_rem(&2);
|
||||
// let sign = if sign == 0 { -1 } else { 1 };
|
||||
// // HACK: Our conventin and the MVA are different, since we are trying to strangle fig this, quick hack.
|
||||
// let offset = Position::in_direction(1 - dim, sign * -1);
|
||||
// let next = Position(i, j) + offset;
|
||||
//
|
||||
// CPosition(next.0, next.1)
|
||||
}
|
||||
|
||||
mod test {
|
||||
use num_integer::Integer;
|
||||
use crate::CPosition;
|
||||
use crate::system::Position;
|
||||
|
||||
pub(crate) fn a(d: u32, i: i32, j: i32) -> CPosition {
|
||||
match d {
|
||||
0 => CPosition(i + 1, j),
|
||||
1 => CPosition(i - 1, j),
|
||||
2 => CPosition(i, j + 1),
|
||||
3 => CPosition(i, j - 1),
|
||||
_ => panic!("Ahh"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn b(d: u32, i: i32, j: i32) -> CPosition {
|
||||
let (dim, sign) = d.div_rem(&2);
|
||||
let sign = if sign == 0 { 1 } else { -1 };
|
||||
// HACK: Our conventin and the MVA are different, since we are trying to strangle fig this, quick hack.
|
||||
let offset = Position::in_direction(dim, sign);
|
||||
let next = Position(i, j) + offset;
|
||||
|
||||
CPosition(next.0, next.1)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let d = [0, 1, 2, 3];
|
||||
d.iter()
|
||||
.map(|d| d.div_rem(&2))
|
||||
.for_each(|p| println!("{p:?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alignment() {
|
||||
let d = [0, 1, 2, 3];
|
||||
d.iter()
|
||||
.map(|d| (a(*d, 0, 0), b(*d, 0, 0)))
|
||||
.for_each(|p| assert_eq!(p.0, p.1));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ pub mod walker;
|
||||
pub mod storage;
|
||||
pub mod model;
|
||||
|
||||
pub const DIM: u32 = 2;
|
||||
pub(crate) const DIM: u32 = 2;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Position(pub i32, pub i32);
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ impl<R: Rng, S: Storage, W: Walker<R>> DLASystem<R, S, W> {
|
||||
running: true,
|
||||
|
||||
storage: VectorStorage::new(6000, 2),
|
||||
walker: LocalRandomWalker,
|
||||
walker: LocalRandomWalker::new(DIM),
|
||||
particles: vec![],
|
||||
active_particle: None,
|
||||
|
||||
|
||||
+13
-2
@@ -13,16 +13,27 @@ pub struct VectorStorage {
|
||||
}
|
||||
|
||||
impl VectorStorage {
|
||||
pub(crate) fn new(grid_size: u32, dim: u32) -> VectorStorage {
|
||||
pub fn new(grid_size: u32, dim: u32) -> VectorStorage {
|
||||
VectorStorage { grid_size, dim, backing: vec![false; grid_size.pow(dim) as usize] }
|
||||
}
|
||||
|
||||
fn linear_index(&self, position: &Position) -> usize {
|
||||
pub fn linear_index(&self, position: &Position) -> usize {
|
||||
assert!(position.0 <= self.grid_size as i32 && -(self.grid_size as i32) <= position.0);
|
||||
assert!(position.1 <= self.grid_size as i32 && -(self.grid_size as i32) <= position.1);
|
||||
|
||||
let x = (position.0 + (self.grid_size as i32) / 2) as usize;
|
||||
let y = (position.1 + (self.grid_size as i32) / 2) as usize;
|
||||
|
||||
return self.grid_size as usize * y + x
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience function for c-binding
|
||||
* */
|
||||
pub fn write(&mut self, position: &Position, val: bool) {
|
||||
let index = self.linear_index(position);
|
||||
self.backing[index] = val;
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage for VectorStorage {
|
||||
|
||||
+10
-4
@@ -1,16 +1,22 @@
|
||||
use num_integer::Integer;
|
||||
use rand::prelude::{Rng, SmallRng};
|
||||
use rand::prelude::Rng;
|
||||
use crate::system::{DIM, Position};
|
||||
|
||||
pub trait Walker<R: Rng> {
|
||||
fn walk(&self, rng: &mut R, position: &Position) -> Position;
|
||||
}
|
||||
|
||||
pub struct LocalRandomWalker;
|
||||
pub struct LocalRandomWalker {
|
||||
dim: u32,
|
||||
}
|
||||
|
||||
impl LocalRandomWalker {
|
||||
pub(crate) fn new(dim: u32) -> LocalRandomWalker { LocalRandomWalker { dim } }
|
||||
}
|
||||
|
||||
impl<R: Rng> Walker<R> for LocalRandomWalker {
|
||||
fn walk(&self, rng: &mut R, position: &Position) -> Position {
|
||||
let (dim, sign) = rng.gen_range(0u32..(DIM * 2)).div_rem(&DIM);
|
||||
let (dim, sign) = rng.gen_range(0u32..(DIM * 2)).div_rem(&self.dim);
|
||||
let sign = if sign == 0 { -1 } else { 1 };
|
||||
let offset = Position::in_direction(dim, sign);
|
||||
|
||||
@@ -26,7 +32,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn uniformity() {
|
||||
let walker = LocalRandomWalker;
|
||||
let walker = LocalRandomWalker::new(2);
|
||||
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
||||
let mut results: Vec<Position> = vec![];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user