diff --git a/Cargo.lock b/Cargo.lock index 045abed..cd39943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,6 +163,17 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -187,7 +198,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dae99b246505811f5bc19d2de1e406ec5d2816b421d58fa223779eb576f472c9" dependencies = [ - "bevy_dylib", "bevy_internal", ] @@ -328,15 +338,6 @@ dependencies = [ "bevy_utils", ] -[[package]] -name = "bevy_dylib" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d193c3d56e3bdd106596327d15dd67ddfd862f8b5aa8260677efefe3ddef736" -dependencies = [ - "bevy_internal", -] - [[package]] name = "bevy_ecs" version = "0.9.1" @@ -930,6 +931,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" +[[package]] +name = "cbindgen" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" +dependencies = [ + "clap 3.2.23", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "tempfile", + "toml", +] + [[package]] name = "cc" version = "1.0.79" @@ -977,6 +997,21 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_lex 0.2.4", + "indexmap", + "strsim", + "termcolor", + "textwrap", +] + [[package]] name = "clap" version = "4.1.8" @@ -985,7 +1020,7 @@ checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" dependencies = [ "bitflags", "clap_derive", - "clap_lex", + "clap_lex 0.3.2", "is-terminal", "once_cell", "strsim", @@ -1005,6 +1040,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "clap_lex" version = "0.3.2" @@ -1705,6 +1749,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.1" @@ -1828,7 +1881,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", "windows-sys 0.45.0", @@ -2663,7 +2716,8 @@ name = "rust-codebase" version = "0.1.0" dependencies = [ "bevy", - "clap", + "cbindgen", + "clap 4.1.8", "csv", "nd_array", "num-integer", @@ -2930,6 +2984,19 @@ dependencies = [ "typenum", ] +[[package]] +name = "tempfile" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.42.0", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -2939,6 +3006,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "thiserror" version = "1.0.38" diff --git a/Cargo.toml b/Cargo.toml index 0f35711..425067f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "dla" +crate-type = ["staticlib"] +path = "src/clib.rs" + [[bin]] name = "model" path = "src/main.rs" @@ -23,8 +28,11 @@ opt-level = 3 [dependencies] clap = { version = "4.1.8", features = ["derive"] } -bevy = { version = "0.9.1", features = ["dynamic"] } +bevy = { version = "0.9.1" } nd_array = "0.1.0" num-integer = "0.1.45" rand = { version = "0.8.5", features = ["default", "small_rng"] } csv = "1.1" + +[build-dependencies] +cbindgen = "0.24.3" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..825ff13 --- /dev/null +++ b/build.rs @@ -0,0 +1,16 @@ +extern crate cbindgen; + +use std::env; +use std::path::Path; +use cbindgen::{Config, Builder}; + +fn main() { + let crate_env = env::var("CARGO_MANIFEST_DIR").unwrap(); + let crate_path = Path::new(&crate_env); + let config = Config::from_root_or_default(crate_path); + Builder::new().with_crate(crate_path.to_str().unwrap()) + .with_config(config) + .generate() + .expect("Cannot generate header file!") + .write_to_file("libdla.h"); +} diff --git a/libdla.h b/libdla.h new file mode 100644 index 0000000..fc72b24 --- /dev/null +++ b/libdla.h @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + +struct CStorage; + +struct CPosition { + int32_t _0; + int32_t _1; +}; + +extern "C" { + +CStorage *storage_new(uint32_t grid_size); + +bool storage_at(const CStorage *storage, int32_t i, int32_t j); + +void storage_deposit(CStorage *storage, int32_t i, int32_t j, uint8_t val); + +CPosition walk(uint32_t d, int32_t i, int32_t j); + +} // extern "C" diff --git a/src/clib.rs b/src/clib.rs new file mode 100644 index 0000000..041823c --- /dev/null +++ b/src/clib.rs @@ -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)); + } +} diff --git a/src/system/mod.rs b/src/system/mod.rs index b9c9b71..0a3c79d 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -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); diff --git a/src/system/model.rs b/src/system/model.rs index 4300676..cdcb399 100644 --- a/src/system/model.rs +++ b/src/system/model.rs @@ -36,7 +36,7 @@ impl> DLASystem { running: true, storage: VectorStorage::new(6000, 2), - walker: LocalRandomWalker, + walker: LocalRandomWalker::new(DIM), particles: vec![], active_particle: None, diff --git a/src/system/storage.rs b/src/system/storage.rs index f2fa541..4a15bb1 100644 --- a/src/system/storage.rs +++ b/src/system/storage.rs @@ -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 { diff --git a/src/system/walker.rs b/src/system/walker.rs index 7fd54c7..0b5c9f2 100644 --- a/src/system/walker.rs +++ b/src/system/walker.rs @@ -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 { 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 Walker 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 = vec![];