diff --git a/Cargo.toml b/Cargo.toml index e90bb63..5515f49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,5 +11,5 @@ rayon = "1.5" bitintr = "0.3.0" itertools = "0.10.2" array-init = "2.0.0" -#ahash = "0.7.6" -#xxhash-rust = {version = "0.8.2", features = ["xxh3"]} +ahash = { version = "0.7.6", optional = true } +xxhash-rust = { version = "0.8.2", features = ["xxh3"], optional = true } diff --git a/src/main.rs b/src/main.rs index adc6d8b..685032b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,93 +1,66 @@ #![allow(dead_code)] #![allow(unused_imports)] -use core::ops::Index; use std::io::{self, Write}; use std::fs; -use std::collections::{HashMap, BTreeMap}; use bitintr::{Lzcnt, Tzcnt}; use regex::Regex; use rayon::prelude::*; use itertools::zip; use array_init::array_init; -// use ahash::{AHasher, RandomState}; -// use xxhash_rust::xxh3::Xxh3; -// use std::hash::BuildHasherDefault; +pub type Charmask = i32; +pub type Achar = i8; // ASCII char -type Charmask = i32; -type Achar = i8; // ASCII char - -const WORD_LENGTH: usize = 5; -const WORD_LENGTH_P: usize = 5; // Padded for SIMD shenanigans -const GUESS_DEPTH: usize = 1; // TODO: Change this whenever working at different depths -const N_SOLUTIONS: usize = 2315; -const CACHE_SIZE: usize = 1<<26; -const IDX_ALL_WORDS: Charmask = (CACHE_SIZE as Charmask) - 1; -const IDX_VALID_SOLUTIONS: Charmask = 0; -const A: Achar = 'A' as Achar; -const Z: Achar = 'Z' as Achar; +pub const WORD_LENGTH: usize = 5; +pub const WORD_LENGTH_P: usize = 5; // Padded for SIMD shenanigans +pub const GUESS_DEPTH: usize = 1; // TODO: Change this whenever working at different depths +pub const N_SOLUTIONS: usize = 2315; +pub const CACHE_SIZE: usize = 1<<26; +pub const IDX_ALL_WORDS: Charmask = (CACHE_SIZE as Charmask) - 1; +pub const IDX_VALID_SOLUTIONS: Charmask = 0; +pub const A: Achar = 'A' as Achar; +pub const Z: Achar = 'Z' as Achar; #[derive(Copy, Clone, Default)] -struct Word { +pub struct Word { charbits: [Charmask; WORD_LENGTH_P], // Each letter in bitmask form charmask: Charmask, // All of the characters contained //letters: [Achar; WORD_LENGTH] } -type TKeys = Charmask; // I give up on making this generic for now -struct ThinArray { - // keys: [TKeys; N_KEYS], - keys: Vec, - items: [T; CAPACITY], - items_used: usize, -} -impl ThinArray { - fn default() -> Self { - // println!("Initializing ThinArray"); - Self{ - // keys: [0; N_KEYS], - items: array_init::array_init(|_| T::default()), - keys: (0..N_KEYS).map(|_| 0).collect(), - items_used: 0, - } - } +#[cfg(use_thin_array)] +mod thin_array; +#[cfg(use_thin_array)] +type WordCache = thin_array::ThinArray, CACHE_SIZE, 7000>; - fn insert(&mut self, key: TKeys, value: T) { - // println!("Insert requested for key {}", key); - debug_assert!(self.items_used < CAPACITY); - self.items_used += 1; - self.items[self.items_used as usize] = value; - // self.items.push(value); - self.keys[key as usize] = self.items_used as TKeys; - } +#[cfg(all(not(use_thin_array), use_hashmap))] +use std::collections::HashMap; +#[cfg(all(not(use_thin_array), use_hashmap))] +type WordCache = HashMap>; // Default hash is slower than BTree on M1 - fn get(&self, key: TKeys) -> &T { - &self.items[self.keys[key as usize] as usize] - } +#[cfg(all(not(use_thin_array), not(use_hashmap), feature = "ahash"))] +use std::collections::HashMap; +#[cfg(all(not(use_thin_array), not(use_hashmap), feature = "ahash"))] +use ahash::{AHasher, RandomState}; +#[cfg(all(not(use_thin_array), not(use_hashmap), feature = "ahash"))] +type WordCache = HashMap, RandomState>; - fn contains_key(&self, _key: &TKeys) -> bool { - true - // key < N_KEYS - } -} -impl Index<&TKeys> for ThinArray { - type Output = T; +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), feature = "xxhash_rust"))] +use std::collections::HashMap; +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), feature = "xxhash_rust"))] +use xxhash_rust::xxh3::Xxh3; +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), feature = "xxhash_rust"))] +use std::hash::BuildHasherDefault; +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), feature = "xxhash_rust"))] +type WordCache = HashMap, BuildHasherDefault>; - fn index(&self, key: &TKeys) -> &T { - // println!("Key requested: {}", key); - &self.items[self.keys[*key as usize] as usize] - } -} +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), not(feature = "xxhash_rust")))] +use std::collections::BTreeMap; +#[cfg(all(not(use_thin_array), not(use_hashmap), not(feature = "ahash"), not(feature = "xxhash_rust")))] +type WordCache = BTreeMap>; -// type WordCache = HashMap, RandomState>; // ahash -// type WordCache = HashMap, BuildHasherDefault>; -// type WordCache = BTreeMap>; -type WordCache = ThinArray, CACHE_SIZE, 7000>; -// type WordCache = HashMap>; // Default hash is slower than BTree on M1 -// type WordCacheArr = [&Vec; CACHE_SIZE]; - fn default_wordcache() -> WordCache { WordCache::default() } diff --git a/src/thin_array.rs b/src/thin_array.rs new file mode 100644 index 0000000..51287e4 --- /dev/null +++ b/src/thin_array.rs @@ -0,0 +1,47 @@ +use core::ops::Index; + +type TKeys = crate::Charmask; // I give up on making this generic for now +pub struct ThinArray { + // keys: [TKeys; N_KEYS], + keys: Vec, + items: [T; CAPACITY], + items_used: usize, +} + +impl ThinArray { + pub fn default() -> Self { + // println!("Initializing ThinArray"); + Self{ + // keys: [0; N_KEYS], + items: array_init::array_init(|_| T::default()), + keys: (0..N_KEYS).map(|_| 0).collect(), + items_used: 0, + } + } + + pub fn insert(&mut self, key: TKeys, value: T) { + // println!("Insert requested for key {}", key); + debug_assert!(self.items_used < CAPACITY); + self.items_used += 1; + self.items[self.items_used as usize] = value; + // self.items.push(value); + self.keys[key as usize] = self.items_used as TKeys; + } + + pub fn get(&self, key: TKeys) -> &T { + &self.items[self.keys[key as usize] as usize] + } + + pub fn contains_key(&self, _key: &TKeys) -> bool { + true + // key < N_KEYS + } +} +impl Index<&TKeys> for ThinArray { + type Output = T; + + fn index(&self, key: &TKeys) -> &T { + // println!("Key requested: {}", key); + &self.items[self.keys[*key as usize] as usize] + } +} \ No newline at end of file