diff --git a/.gitignore b/.gitignore index 4e30131..f19363a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /target **/*.rs.bk -Cargo.lock bin/ -pkg/ +pkg*/ wasm-pack.log diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..28f5b9e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,456 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-counter" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f447d68cfa5a9ab0c1c862a703da2a65b5ed1b7ce1153c9eb0169506d56019" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if 1.0.0", + "lazy_static", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "enum-map" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348b2a57c82f98b9dbd8098b1abb2416f221823d3e50cbe24eaebdd16896826" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a63b7a0ddec6f38dcec5e36257750b7a8fcaf4227e12ceb306e341d63634da05" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "java-rand" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2007b51b83dc078bc08617dab8f41d7abd61bce0e7732f79e1d01219bf0add80" + +[[package]] +name = "js-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.124" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" + +[[package]] +name = "libenchcrack" +version = "1.0.0" +dependencies = [ + "atomic-counter", + "enum-map", + "java-rand", + "js-sys", + "rayon", + "strum", + "strum_macros", + "wasm-bindgen", + "wasm-bindgen-rayon", + "wasm-bindgen-test", + "web-sys", + "wee_alloc", +] + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "proc-macro2" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "spmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5" + +[[package]] +name = "strum" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" + +[[package]] +name = "strum_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df87c67450805c305d3ae44a3ac537b0253d029153c25afc3ecd2edc36ccafb1" +dependencies = [ + "js-sys", + "rayon", + "spmc", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4464b3f74729a25f42b1a0cd9e6a515d2f25001f3535a6cfaf35d34a4de3bab" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c5a6f82cc6093a321ca5fb3dc9327fe51675d477b3799b4a9375bac3b7b4c" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "web-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wee_alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "memory_units", + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 3442b7d..27e3a4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,29 +1,30 @@ [package] name = "libenchcrack" description = "Code for cracking minecraft's XP seed" -version = "0.2.0" +version = "1.0.0" authors = ["ImUrX "] repository = "https://github.com/ImUrX/libenchcrack" -edition = "2018" +edition = "2021" license = "MIT" [lib] crate-type = ["cdylib", "rlib"] [dependencies] -wasm-bindgen = "0.2.75" +wasm-bindgen = "0.2.80" wee_alloc = "0.4.5" -js-sys = "0.3.52" +js-sys = "0.3.57" java-rand = "0.2.0" -enum-map = "0.6.4" -strum = "0.21.0" -strum_macros = "0.21.1" -rayon = { version = "1.5.1", optional = true } -wasm-bindgen-rayon = { version = "1.0.3", optional = true, features = ["no-bundler"] } +enum-map = "2.1.0" +strum = "0.24" +strum_macros = "0.24" +rayon = { version = "1.5", optional = true } +wasm-bindgen-rayon = { version = "1.0", optional = true, features = ["no-bundler"] } +atomic-counter = { version = "1.0.1", optional = true } [dev-dependencies] -wasm-bindgen-test = "0.3.25" -web-sys = { version = "0.3.52", features = ["console"] } +wasm-bindgen-test = "0.3.30" +web-sys = { version = "0.3.57", features = ["console"] } [profile.release] # Tell `rustc` to optimize for small code size. @@ -31,4 +32,4 @@ opt-level = 3 lto = true [features] -threads = ["rayon", "wasm-bindgen-rayon"] +threads = ["rayon", "wasm-bindgen-rayon", "atomic-counter"] diff --git a/src/lib.rs b/src/lib.rs index a215c23..f351e77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,12 +17,15 @@ use std::ops::Range; #[cfg(feature = "threads")] use rayon::prelude::*; -#[global_allocator] +#[cfg_attr( + all(target_family = "wasm", not(feature = "threads")), + global_allocator +)] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; const PREALLOC_SIZE: usize = 80e6 as usize; -#[cfg(feature = "threads")] +#[cfg(all(target_family = "wasm", feature = "threads"))] pub use wasm_bindgen_rayon::init_thread_pool; #[wasm_bindgen] @@ -53,6 +56,26 @@ impl From for (i32, i32, i32, i32) { } } +/*pub trait Cracker { + // Resets state of cracker + fn reset(&self); + + // Current amount of possible remaining seeds + fn possible_seeds(&self) -> usize; + + // Returns first seed (used when remaining seeds is 1 usually) + fn seed(&self) -> i32; + + // First input accepts two table infos so it uses less memory + fn first_input(&mut self, info: EnchantmentTableInfo, info2: EnchantmentTableInfo); + + // Compare enchantment table info to current seeds and filters which ones are not + fn add_input(&mut self, info: EnchantmentTableInfo); + + // Returns if the cracker contains such seed + fn contains(&self, x: i32) -> bool; +}*/ + #[wasm_bindgen] pub struct Cracker { possible_seeds: Vec, @@ -89,10 +112,11 @@ impl Cracker { #[cfg(feature = "threads")] #[wasm_bindgen(constructor)] - pub fn new() -> Self { + pub fn new(_thread_id: usize, _threads: usize) -> Self { Cracker { possible_seeds: Vec::with_capacity(PREALLOC_SIZE), rng: Default::default(), + counter: atomic_counter } } @@ -179,13 +203,10 @@ pub struct Manipulator { impl Manipulator { #[wasm_bindgen(constructor)] pub fn new(seed1: u32, seed2: u32) -> Option { - match Self::calculate_seed(seed1, seed2) { - Some(player_seed) => Some(Self { - player_seed, - items: Default::default(), - }), - None => None, - } + Self::calculate_seed(seed1, seed2).map(|player_seed| Self { + player_seed, + items: Default::default(), + }) } fn calculate_seed(seed1: u32, seed2: u32) -> Option { @@ -214,13 +235,9 @@ impl Manipulator { } #[wasm_bindgen(getter = playerSeed)] - pub fn player_seed(&self) -> js_sys::Uint8Array { - let array = js_sys::Uint8Array::new_with_length(6); - let bytes = self.player_seed.to_le_bytes(); - for i in (0..array.length()).rev() { - array.set_index(i, bytes[i as usize]); - } - array + pub fn player_seed(&self) -> Box<[u8]> { + let bytes: [u8; 8] = self.player_seed.to_le_bytes(); + bytes[0..6].into() } #[wasm_bindgen] @@ -230,9 +247,8 @@ impl Manipulator { max_shelves: i32, player_level: i32, version: Version, - ) -> Option { + ) -> Option> { let mut seed = self.player_seed; - let array = js_sys::Int32Array::new_with_length(3); if self.items[item].enchantments.is_empty() { return None; } @@ -351,10 +367,7 @@ impl Manipulator { } } - array.set_index(0, times_needed); - array.set_index(1, slot + 1); - array.set_index(2, bookshelves_needed); - Some(array) + Some([times_needed, slot + 1, bookshelves_needed].into()) } #[wasm_bindgen(js_name = updateSeed)] diff --git a/src/utils.rs b/src/utils.rs index dceeda0..d010a0c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,17 @@ +#[cfg(target_feature = "simd128")] +use std::arch::wasm32::*; use std::cmp; use std::num::Wrapping; const MULT: i64 = 0x5DEECE66D; +#[cfg(target_feature = "simd128")] +#[allow(non_upper_case_globals)] +const MULTx2: v128 = i64x2(MULT, MULT); + const MASK: i64 = (1 << 48) - 1; +#[cfg(target_feature = "simd128")] +#[allow(non_upper_case_globals)] +const MASKx2: v128 = i64x2(MASK, MASK); #[derive(Default)] pub struct SimpleRandom { @@ -72,3 +81,234 @@ impl SimpleRandom { && self.levels_slot3(shelves) == slot3 } } + +/* +#[cfg(target_feature = "simd128")] +pub struct SIMDSimpleRandom { + pub seeds: [v128; 2], //supposedly 2 i64x2 +} + +#[cfg(target_feature = "simd128")] +impl SIMDSimpleRandom { + pub fn set_seed(&mut self, seeds: [v128; 2]) { + //self.seed = (seed ^ MULT) & MASK; + self.seeds = seeds.map(|seed| v128_and(v128_xor(seed, MULTx2), MASKx2)) + } + + pub fn next_int(&mut self) -> v128 { + //supposedly i32x4 + //self.seed = (Wrapping(self.seed) * Wrapping(MULT) + Wrapping(0xB)).0 & MASK; + //(self.seed as u64 >> 17) as i32 + self.seeds = self + .seeds + .map(|seed| v128_and(i64x2_add(i64x2_mul(seed, MULTx2), i64x2_splat(0xB)), MASKx2)); + let unsigned: [v128; 2] = self.seeds.map(|seed| u64x2_shr(seed, 17)); + i32x4( + i64x2_extract_lane::<0>(unsigned[0]) as i32, + i64x2_extract_lane::<1>(unsigned[0]) as i32, + i64x2_extract_lane::<0>(unsigned[1]) as i32, + i64x2_extract_lane::<1>(unsigned[1]) as i32, + ) + } + + pub fn get_seed(&self, index: usize) -> i64 { + let i = if index > 1 { 1 } else { 0 }; + match index { + 0 => i64x2_extract_lane::<0>(self.seeds[i]), + 1 => i64x2_extract_lane::<1>(self.seeds[i]), + 2 => i64x2_extract_lane::<0>(self.seeds[i]), + 3 => i64x2_extract_lane::<1>(self.seeds[i]), + _ => panic!("The total size is 4!"), + } + } + + pub fn replace_seed(&mut self, seed: i64, index: usize) { + let i = if index > 1 { 1 } else { 0 }; + self.seeds[i] = match index { + 0 => i64x2_replace_lane::<0>(self.seeds[i], seed), + 1 => i64x2_replace_lane::<1>(self.seeds[i], seed), + 2 => i64x2_replace_lane::<0>(self.seeds[i], seed), + 3 => i64x2_replace_lane::<1>(self.seeds[i], seed), + _ => panic!("The total size is 4!"), + } + } + + pub fn next_int_indexed(&mut self, index: usize) -> i32 { + let mut seed: i64 = self.get_seed(index); + seed = (Wrapping(seed) * Wrapping(MULT) + Wrapping(0xB)).0 & MASK; + self.replace_seed(seed, index); + (seed as u64 >> 17) as i32 + } + + pub fn next_int_bound(&mut self, bound_num: i32) -> v128 { + //supposedly i32x4 + /*let mut r = Wrapping(self.next_int()); + let m = bound - Wrapping(1); + if (bound & m) == Wrapping(0) { + r = Wrapping(((bound.0 as i64 * r.0 as i64) >> 31) as i32); + } else { + let mut u = r; + while { + r = u % bound; + u - r + m + } + .0 < 0 + { + u = Wrapping(self.next_int()); + } + } + r.0*/ + let bound = i32x4_splat(bound_num); + let mut r = self.next_int(); + let m_num = (Wrapping(bound_num) - Wrapping(1)).0; + if (bound_num & m_num) == 0 { + let high = i64x2_shr(i64x2_extmul_high_i32x4(bound, r), 31); + let low = i64x2_shr(i64x2_extmul_low_i32x4(bound, r), 31); + return i32x4( + i64x2_extract_lane::<0>(low) as i32, + i64x2_extract_lane::<1>(low) as i32, + i64x2_extract_lane::<0>(high) as i32, + i64x2_extract_lane::<1>(high) as i32, + ); + } + + let m = i32x4_splat(m_num); + let boundf = f32x4_convert_i32x4(bound); + let mut u = r; + let mut flags = [false; 4]; + loop { + r = i32x4_sub( + u, + i32x4_mul( + i32x4_trunc_sat_f32x4(f32x4_div(f32x4_convert_i32x4(u), boundf)), + bound, + ), + ); + let comp = i32x4_lt(i32x4_add(i32x4_sub(u, r), m), i32x4_splat(0)); + if !i32x4_all_true(comp) { + flags[0] = i32x4_extract_lane::<0>(comp) != 0; + flags[1] = i32x4_extract_lane::<1>(comp) != 0; + flags[2] = i32x4_extract_lane::<2>(comp) != 0; + flags[3] = i32x4_extract_lane::<3>(comp) != 0; + break; + } + u = self.next_int(); + } + + for i in 0..4 { + if !flags[i] { + continue; + } + let mut u_num = get_i32(u, i); + let mut res_num: i32; + loop { + res_num = u_num % bound_num; + if (u_num - res_num + m_num) >= 0 { + break; + } + u_num = self.next_int_indexed(i); + } + r = match i { + 0 => i32x4_replace_lane::<0>(r, res_num), + 1 => i32x4_replace_lane::<1>(r, res_num), + 2 => i32x4_replace_lane::<2>(r, res_num), + 3 => i32x4_replace_lane::<3>(r, res_num), + _ => panic!("The total size is 4!"), + }; + } + r + } + + // ported from https://github.com/vectorclass/version2/blob/v2.01.04/vectori128.h#L6534 + fn divide_by_3(num: v128) -> v128 { + let mul = i32x4_splat(-1431655765); + //let s1 = i32x4(1, 0, 0, 0); + let t1 = i64x2_extmul_low_i32x4(num, mul); + let t2 = u64x2_shr(t1, 32); + let t4 = i64x2_extmul_high_i32x4(num, mul); + let t7 = v128_bitselect(t2, t4, i16x8_splat(0xCC)); + let t8 = i32x4_add(t7, num); + let t9 = i32x4_replace_lane::<0>(t8, i32x4_extract_lane::<0>(t8) >> 1); + let t10 = i32x4_shr(num, 31); + i32x4_sub(t9, t10) + } + + fn generic_enchantibility(&mut self, shelves: i32) -> v128 { + let first = self.next_int_bound(8); + let second = self.next_int_bound(shelves + 1); + //first + 1 + (shelves >> 1) + second + i32x4_add( + i32x4_add(first, i32x4_splat(1)), + i32x4_add(i32x4_splat(shelves >> 1), second), + ) + } + + fn levels_slot1(&mut self, shelves: i32) -> v128 { + /*let slot1 = self.generic_enchantibility(shelves) / 3; + if slot1 < 1 { + 1 + } else { + slot1 + }*/ + let slot1 = SIMDSimpleRandom::divide_by_3(self.generic_enchantibility(shelves)); + v128_bitselect(slot1, i32x4_splat(1), i32x4_lt(slot1, i32x4_splat(1))) + } + + fn levels_slot2(&mut self, shelves: i32) -> v128 { + //(self.generic_enchantibility(shelves) * 2 / 3) + 1 + i32x4_add( + SIMDSimpleRandom::divide_by_3(i32x4_mul( + self.generic_enchantibility(shelves), + i32x4_splat(2), + )), + i32x4_splat(1), + ) + } + + fn levels_slot3(&mut self, shelves: i32) -> v128 { + //cmp::max(self.generic_enchantibility(shelves), shelves * 2) + i32x4_max( + self.generic_enchantibility(shelves), + i32x4_splat(shelves * 2), + ) + } + + pub fn verify_seed( + &mut self, + seed: v128, + (shelves, slot1, slot2, slot3): (i32, i32, i32, i32), + ) -> [bool; 4] { + let mut res = [true; 4]; + self.set_seed([i64x2_extend_low_i32x4(seed), i64x2_extend_high_i32x4(seed)]); + let slot1_calc = i32x4_eq(self.levels_slot1(shelves), i32x4_splat(slot1)); + if !i32x4_all_true(slot1_calc) { + for i in 0..4 { + res[i] = get_i32(slot1_calc, i) != 0; + } + } + let slot2_calc = i32x4_eq(self.levels_slot2(shelves), i32x4_splat(slot2)); + if !i32x4_all_true(slot2_calc) { + for i in 0..4 { + res[i] = get_i32(slot2_calc, i) != 0; + } + } + let slot3_calc = i32x4_eq(self.levels_slot3(shelves), i32x4_splat(slot3)); + if !i32x4_all_true(slot3_calc) { + for i in 0..4 { + res[i] = get_i32(slot3_calc, i) != 0; + } + } + res + } +} + +#[cfg(target_feature = "simd128")] +fn get_i32(vec: v128, index: usize) -> i32 { + match index { + 0 => i32x4_extract_lane::<0>(vec), + 1 => i32x4_extract_lane::<1>(vec), + 2 => i32x4_extract_lane::<2>(vec), + 3 => i32x4_extract_lane::<3>(vec), + _ => panic!("The total size is 4!"), + } +}*/