From 511ce04f0b72a003a8fb429510bb62bd04ebf013 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 26 Dec 2023 21:28:46 +0100 Subject: [PATCH] new Matcher --- Cargo.toml | 3 +- Makefile | 4 +- schemsearch-lib/Cargo.toml | 3 + schemsearch-lib/build.rs | 7 ++ schemsearch-lib/src/compare.c | 69 +++++++++++++++++++ schemsearch-lib/src/lib.rs | 124 +++++++++++++++++++++++++--------- tests/Pattern.nbt | Bin 0 -> 228 bytes tests/Random.nbt | Bin 0 -> 256 bytes 8 files changed, 176 insertions(+), 34 deletions(-) create mode 100644 schemsearch-lib/build.rs create mode 100644 schemsearch-lib/src/compare.c create mode 100644 tests/Pattern.nbt create mode 100644 tests/Random.nbt diff --git a/Cargo.toml b/Cargo.toml index 03d056b..f8232a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,5 @@ opt-level = "z" codegen-units = 1 [profile.release] -lto = true \ No newline at end of file +lto = true +opt-level = 3 \ No newline at end of file diff --git a/Makefile b/Makefile index 1527be6..73f61e9 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ default: @echo "Building (Release)..."; - cargo rustc --release --color=always -p schemsearch-cli -- -C target-feature=+avx2 + cargo rustc --release --color=always -p schemsearch-cli -- -C target-cpu=native sql: @echo "Building (Release)..."; - cargo rustc --release --color=always -p schemsearch-cli --features sql -- -C target-feature=+avx2 + cargo rustc --release --color=always -p schemsearch-cli --features sql -- -C target-cpu=native debug: @echo "Building (Debug)..."; diff --git a/schemsearch-lib/Cargo.toml b/schemsearch-lib/Cargo.toml index b55e846..473e67c 100644 --- a/schemsearch-lib/Cargo.toml +++ b/schemsearch-lib/Cargo.toml @@ -11,3 +11,6 @@ serde = { version = "1.0.160", features = ["derive"] } schemsearch-files = { path = "../schemsearch-files" } named-binary-tag = "0.6" libmath = "0.2.1" + +[build-dependencies] +cc = { version = "1.0.83", features = [] } diff --git a/schemsearch-lib/build.rs b/schemsearch-lib/build.rs new file mode 100644 index 0000000..13a5446 --- /dev/null +++ b/schemsearch-lib/build.rs @@ -0,0 +1,7 @@ +use cc; + +fn main() { + cc::Build::new() + .file("src/compare.c") + .compile("compare"); +} \ No newline at end of file diff --git a/schemsearch-lib/src/compare.c b/schemsearch-lib/src/compare.c new file mode 100644 index 0000000..b74dd75 --- /dev/null +++ b/schemsearch-lib/src/compare.c @@ -0,0 +1,69 @@ +#include + +int32_t isMatching( + const int32_t *schem_data, + const int32_t *pattern_data, + size_t pattern_data_length, + int32_t x, + int32_t y, + int32_t z, + int32_t schem_width, + int32_t schem_length, + int32_t pattern_width, + int32_t pattern_height, + int32_t pattern_length, + int32_t *w_ptr + ) { + for (int j = 0; j < pattern_height; ++j) { + for (int k = 0; k < pattern_length; ++k) { + int pattern_index_pre = k * pattern_width + j * pattern_width * pattern_length; + int schem_index_pre = x + (k + z) * schem_width + (j + y) * schem_width * schem_length; + for (int i = 0; i < pattern_width; ++i) { + int pattern_index = i + pattern_index_pre; + int schem_index = i + schem_index_pre; + w_ptr[pattern_index] = schem_data[schem_index]; + } + } + } + + int32_t matching = 0; + for (int i = 0; i < pattern_data_length; ++i) { + matching += w_ptr[i] == pattern_data[i]; + } + + return matching; +} + +void is_matching_all( + const int32_t *schem_data, + const int32_t *pattern_data, + size_t schem_width, + size_t schem_height, + size_t schem_length, + size_t pattern_width, + size_t pattern_height, + size_t pattern_length, + int32_t *result +) { + for (size_t pz = 0; pz < pattern_length; ++pz) { + size_t maxZ = schem_length - pattern_length + pz + 1; + for (size_t py = 0; py < pattern_height; ++py) { + size_t maxY = schem_height - pattern_height + py + 1; + for (size_t px = 0; px < pattern_width; ++px) { + int32_t pv = pattern_data[px + py * pattern_width + pz * pattern_width * pattern_height]; + size_t maxX = schem_width - pattern_width + px + 1; + for (size_t z = pz; z < maxZ; ++z) { + size_t sourceOffsetZ = z * schem_width * schem_height; + size_t resultOffsetZ = (z - pz) * schem_width * schem_height - py * schem_width; + for (size_t y = py; y < maxY; ++y) { + size_t sourceOffsetY = sourceOffsetZ + y * schem_width; + size_t resultOffsetY = resultOffsetZ + y * schem_width - px; + for (size_t x = px; x < maxX; ++x) { + result[resultOffsetY + x] += schem_data[sourceOffsetY + x] == pv; + } + } + } + } + } + } +} diff --git a/schemsearch-lib/src/lib.rs b/schemsearch-lib/src/lib.rs index d3edec1..5dfb43c 100644 --- a/schemsearch-lib/src/lib.rs +++ b/schemsearch-lib/src/lib.rs @@ -33,6 +33,36 @@ pub struct SearchBehavior { pub threshold: f32, } +extern "C" { + pub fn isMatching( + schem_data: *const i32, + pattern_data: *const i32, + pattern_data_length: usize, + x: usize, + y: usize, + z: usize, + schem_width: usize, + schem_length: usize, + pattern_width: usize, + pattern_height: usize, + pattern_length: usize, + w_ptr: *mut i32, + ) -> i32; + + + pub fn is_matching_all( + schem_data: *const i32, + pattern_data: *const i32, + schem_width: usize, + schem_height: usize, + schem_length: usize, + pattern_width: usize, + pattern_height: usize, + pattern_length: usize, + result: *mut i32 + ); +} + pub fn search( schem: SpongeSchematic, pattern_schem: &SpongeSchematic, @@ -62,7 +92,8 @@ pub fn search( let air_id = if search_behavior.ignore_air || search_behavior.air_as_any { pattern_schem.palette.get("minecraft:air").unwrap_or(&-1) } else { &-1}; - let pattern_blocks = pattern_schem.block_data.len() as f32; + let pattern_blocks_usize = pattern_schem.block_data.len(); + let pattern_blocks = pattern_blocks_usize as f32; let i_pattern_blocks = pattern_blocks as i32; let pattern_width = pattern_schem.width as usize; @@ -75,44 +106,75 @@ pub fn search( let skip_amount = ceil((pattern_blocks * (1.0 - search_behavior.threshold)) as f64, 0) as i32; - for y in 0..=schem_height - pattern_height { + /*for y in 0..=schem_height - pattern_height { for z in 0..=schem_length - pattern_length { for x in 0..=schem_width - pattern_width { - let mut not_matching = 0; - 'outer: - for j in 0..pattern_height { - for k in 0..pattern_length { - 'inner: - for i in 0..pattern_width { - let index = (x + i) + schem_width * ((z + k) + (y + j) * schem_length); - let pattern_index = i + pattern_width * (k + j * pattern_length); - let data = unsafe { *schem_data.add(index) }; - let pattern_data = unsafe { *pattern_data.add(pattern_index) }; - if (search_behavior.ignore_air && data != *air_id) || (search_behavior.air_as_any && pattern_data != *air_id) { - continue 'inner; - } - if data != pattern_data { - not_matching += 1; - if not_matching >= skip_amount { - break 'outer; - } - } - } - } - } + let matching_count; + unsafe { + matching_count = isMatching( + schem_data, + pattern_data, + pattern_blocks_usize, + x, + y, + z, + schem_width, + schem_length, + pattern_width, + pattern_height, + pattern_length, + w_ptr, + ); + }; - if not_matching < skip_amount { - matches.push(Match { - x: x as u16, - y: y as u16, - z: z as u16, - percent: (i_pattern_blocks - not_matching) as f32 / pattern_blocks, - }); + if matching_count >= i_pattern_blocks - skip_amount { + let percent = matching_count as f32 / pattern_blocks; + if percent >= search_behavior.threshold { + matches.push(Match { + x: x as u16, + y: y as u16, + z: z as u16, + percent, + }); + } } } } + }*/ + + let mut result = Vec::::with_capacity(schem_width * schem_height * schem_length); + result.resize(schem_width * schem_height * schem_length, 0); + + unsafe { + is_matching_all( + schem_data, + pattern_data, + schem_width, + schem_height, + schem_length, + pattern_width, + pattern_height, + pattern_length, + result.as_mut_ptr() + ); } + dbg!(result.clone()); + + result.into_iter().enumerate().filter(|(_, matching_count)| *matching_count >= i_pattern_blocks - skip_amount).for_each(|(i, matching_count)| { + let percent = matching_count as f32 / pattern_blocks; + let x = i % schem_width; + let y = (i / schem_width) % schem_height; + let z = i / (schem_width * schem_height); + matches.push(Match { + x: x as u16, + y: y as u16, + z: z as u16, + percent, + }); + + }); + return matches; } diff --git a/tests/Pattern.nbt b/tests/Pattern.nbt new file mode 100644 index 0000000000000000000000000000000000000000..76671b91e058a5ee73bcf82d4e1fc4a5ba368da1 GIT binary patch literal 228 zcmVH^gV(99DeTP!Lx2MM8VqhGhw~ z7v_Gw-ptJo10kG`d+tew^tI|}quEpn*^9QsOiTR*KxIe{gu?a4II4Qx@ZFBA_1n*_ z_f}kI3bRpbdm?v~pl~%xJ=I4c5+zwtKN#-wCQbvbZ&jM4zzgBjBnlm literal 0 HcmV?d00001 diff --git a/tests/Random.nbt b/tests/Random.nbt new file mode 100644 index 0000000000000000000000000000000000000000..a53a57edb7b4b38bdfd0fc53259c728c5e6cdd32 GIT binary patch literal 256 zcmV+b0ssCViwFP!00000|5Z;-OT;h`oo3vvZS^AV!QUW=XK#uX4=yeUcJ(5mowmVj zx}+nk|6S0DZta>7hMD&LO2>RPt^dR-1w1vZ#oz36-@8QHQd4^h5b3P zt~6_e?B=q_N1mvXBEPTep7`lY&QAX