diff --git a/Cargo.lock b/Cargo.lock index 98e140e..d2fd767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,18 +77,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "indoc" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" - [[package]] name = "kolmogorov_smirnov" version = "1.1.0" @@ -120,15 +108,6 @@ dependencies = [ "rawpointer", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.8.3" @@ -204,19 +183,12 @@ dependencies = [ "libm", ] -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - [[package]] name = "onod3000" version = "0.1.0" dependencies = [ "flate2", "kolmogorov_smirnov", - "pyo3", "statrs", ] @@ -226,12 +198,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "portable-atomic" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -250,69 +216,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "pyo3" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc" -dependencies = [ - "cfg-if", - "indoc", - "libc", - "memoffset", - "once_cell", - "portable-atomic", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-macros" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4" -dependencies = [ - "heck", - "proc-macro2", - "pyo3-build-config", - "quote", - "syn", -] - [[package]] name = "quote" version = "1.0.38" @@ -460,12 +363,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "typenum" version = "1.17.0" @@ -478,12 +375,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" -[[package]] -name = "unindent" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index b625ad1..9aa3b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,24 +3,7 @@ name = "onod3000" version = "0.1.0" edition = "2021" -[lib] -name = "onod3000" -crate-type = ["cdylib", "staticlib", "lib"] - [dependencies] flate2 = "1.0.35" kolmogorov_smirnov = "1.1.0" -pyo3 = {version = "0.23.4", optional = true} statrs = "0.18.0" - -[features] -python = ["dep:pyo3"] - -[[bin]] -name="onod3000" -file="src/bin/onod3000.rs" - -[profile.release] -lto = true -codegen-units = 1 -panic = "abort" \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index dfd9277..0000000 --- a/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -MIT License - -Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ---- - -This project is a Rust port of the original Java implementation by Paul Uszak. -Original work is licensed under the terms specified in the respective file header. \ No newline at end of file diff --git a/include/onod3000.h b/include/onod3000.h deleted file mode 100644 index cfd07c1..0000000 --- a/include/onod3000.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Returns true on success. Writes three doubles: obs, z, p -bool onod_run(const char* test, - const uint8_t* samples, - size_t len, - double* result /* length >= 3 */); - -#ifdef __cplusplus -} -#endif diff --git a/readme.md b/readme.md deleted file mode 100644 index 8b34495..0000000 --- a/readme.md +++ /dev/null @@ -1,201 +0,0 @@ -> **Migrated to [code.randogoth.com/randogoth/onod3000](https://code.randogoth.com/randogoth/onod3000)** - -``` -                         ____                    -                    |\   ` //  /\\   /\\   /\\   -                     \\   //  || || || || || ||  -  /'\\ \\/\\  /'\\  / \\  \\  || || || || || ||  - || || || || || || || ||   )) || || || || || ||  - || || || || || || || ||  //  || || || || || ||  - \\,/  \\ \\ \\,/   \\/  /'    \\/   \\/   \\/   -                                                 - - Rust port of Paul Uszak's new randomness testing suite for TRNG Makers - generating in the sub 1 MB space. Successor to John Walker’s venerable `ent`. - - Pipe binary entropy data into the `onod3000` command line tool or call it - with `-f ` to load entropy from a file. - -``` - -`Onod3000` provides multiple randomness tests, each outputting a statistic, a z-score andd a p-value to assess the conformity of the data to random behavior. - -## Testing Methodology - -- **Null Hypothesis**: The data conforms to random behavior. -- **P-Value Interpretation**: Low p-values (< 0.01) indicate a significant deviation from randomness. - -All tests have been carefully ported from [Paul Uszak's Java code](http://www.reallyreallyrandom.com/gitbucketlabhub/) (ent3000-0.6.0-beta). Java libraries were substituted with Rust crate equivalents when possible. The suite includes the following tests: - -- **Monobit Test**: Evaluates the balance of 0s and 1s. -- **Chi-Square Tests**: Tests the uniformity of bits and bytes. -- **MeanByte Test**: Checks if the mean byte value aligns with expected randomness. -- **Kolmogorov-Smirnov (KS) Test**: Assesses uniformity of data distribution. -- **Pi Test**: Uses Monte Carlo methods to approximate π. -- **Shells Test**: Analyzes distances in 3D space. -- **Gaps Test**: Measures gaps between occurrences of a specific value. -- **Avalanche Test**: Analyzes bit-level changes in data chunks. -- **Runs and RunUps Tests**: Checks for sequential patterns in data. -- **Prediction Test**: Assesses the predictability of next bits. -- **UnCorrelation Test**: Evaluates correlation between shifted data. - -More details on some individual tests [available here](http://www.reallyreallyrandom.com/ent3000/the-tests/index.html) - -### Sample Output -```bash -cat /dev/random | head -c 259200 | onod3000 - -Testing 259200 bytes from stdin. --------------------------------------------------------- -Randomness Test Value Z-Score P-Value Pass --------------------------------------------------------- -Shannon 7.999 -0.3669 0.7137 ✅ -Monobit 0.500 0.9000 0.3681 ✅ -ChiBit 4.555 -0.8612 0.8039 ✅ -ChiByte 236.288 -0.8286 0.7939 ✅ -MeanByte 127.312 -1.2970 0.1946 ✅ -Compression 1.000 0.0868 0.9308 ✅ -Kolm.-Smirnov 0.004 2.0722 0.0272 ✅ -Pi 3.139 -1.3171 0.1878 ✅ -Shells 33.593 -0.0493 0.4874 ✅ -Gaps 7.402 -0.3767 0.5954 ✅ -Avalanche 80.006 0.0009 0.9993 ✅ -Runs 129288.000 0.8208 0.4118 ✅ -RunUps 2.647 1.1645 0.1038 ✅ -Prediction 0.500 -0.0255 0.9796 ✅ -UnCorrelation -0.001 -0.3725 0.7096 ✅ --------------------------------------------------------- -15/15 tests passed. --------------------------------------------------------- -``` - -## Rust Library - -```rust -use onod3000::Onod; - -fn main() { - let data = vec![...]; // Your binary data - let p_value = Onod::monobit(&data); - println!("Monobit Test P-Value: {:.4}", p_value); -} -``` - -## Bindings - -The library ships with FFI and optional Python bindings so it can be used as C or Python library. - -### Python -Install using `maturin`: -```bash -maturin build --release --features python -``` - -## Comparison - -To test the implementation three files of binary random data have been analyzed using the original Java program (version 0.6.0-beta) and this Rust port, expecting the same p-values. The test files can be found in the test folder. - -### Testing 1024 bytes from test1.bin (/dev/random) - -Test | Java ent3000 | Rust onod3000 | Note | -------------- | ------------ | ------------- | ------------- | -Shannon | N/A | 0.0000 | | -Monobit | 0.6746 | 0.6746 | | -ChiBit | 0.9299 | 0.9299 | | -ChiByte | 0.9819 | 0.9819 | | -MeanByte | 0.7964 | 0.7964 | | -Compression | N/A | 0.0146 | | -KS | 0.5313 | 0.2476 | Mismatch | -Pi | 0.3784 | 0.3784 | | -Shells | 0.7559 | 0.7559 | | -Gaps | 0.0000 | 0.0000 | | -Avalanche | 0.8794 | 0.8794 | | -Runs | 0.0850 | 0.0850 | | -RunUps | 0.6537 | 0.6537 | | -Prediction | 0.6164 | 0.6164 | | -UnCorrelation | 0.0921 | 0.0918 | Close enough | - -Feel free to provide more results, and I'll continue updating the table! - -### Testing 259,200 bytes from test2.bin (/dev/random) - -Test | Java ent3000 | Rust onod3000 | Note | -------------- | ------------ | ------------- | ------------- | -Shannon | N/A | 0.6853 | | -Monobit | 0.2103 | 0.2103 | | -ChiBit | 0.5590 | 0.5590 | | -ChiByte | 0.3748 | 0.3748 | | -MeanByte | 0.0183 | 0.0183 | | -Compression | N/A | 0.9308 | | -KS | 0.2900 | 0.0178 | Mismatch | -Pi | 0.9765 | 0.9765 | | -Shells | 0.7235 | 0.7235 | | -Gaps | 0.6425 | 0.6425 | | -Avalanche | 0.9995 | 0.9995 | | -Runs | 0.3310 | 0.3310 | | -RunUps | 0.9393 | 0.9393 | | -Prediction | 0.1519 | 0.1519 | | -UnCorrelation | 0.4497 | 0.4497 | | - -### Testing 259,200 bytes from test3.bin (Hardware QRNG) - -Test | Java ent3000 | Rust onod3000 | Note | -------------- | ------------ | ------------- | ---- | -Shannon | N/A | 0.6978 | | -Monobit | 0.4926 | 0.4926 | | -ChiBit | 0.8428 | 0.8428 | | -ChiByte | 0.5785 | 0.5785 | | -MeanByte | 0.9601 | 0.9601 | | -Compression | N/A | 0.9308 | | -KS | 0.7395 | 0.0441 | Mismatch | -Pi | 0.2806 | 0.2806 | | -Shells | 0.7711 | 0.7711 | | -Gaps | 0.1937 | 0.1937 | | -Avalanche | 0.9932 | 0.9932 | | -Runs | 0.2500 | 0.2500 | | -RunUps | 0.9710 | 0.9710 | | -Prediction | 0.7173 | 0.7173 | | -UnCorrelation | 0.4674 | 0.4674 | | - -### Conclusions - -Although the implementation of the randomness tests closely follows the original Java logic, differences in the results arise in the Kolmogorov-Smirnov test. The external libraries used for running the test probably differ in their implementation. Also the uniform distribution to test against is provided by the Apache Commons Math library. Since it would be way beyond the scope of this porting project to try to fully match the functionality of the dependencies used we just accept the minor difference. Another issue might be that Java emphasizes predictability and portability, enforcing strict IEEE 754 behavior across platforms. Rust on the other hand prioritizes performance and flexibility, allowing platform-specific optimizations that may deviate slightly from strict IEEE semantics. - -These differences are generally negligible for practical purposes and do not affect the overall functionality or -statistical significance of the test. - -### Bonus - -We implemented a Well Equidistributed Long-period Linear pseudo-random number generator that is used with a random seed derived from an epoch timestamp that is being used as uniform distribution for the KS test. - -## License - -This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. - -### License of Original Java Implementation - -``` -Copyright (c) 2023 Paul Uszak. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -``` - -## Credits - -This work was made possible with the invaluable assistance of OpenAI's ChatGPT, which provided guidance, debugging help, and inspiration throughout the development process. \ No newline at end of file diff --git a/src/bin/onod3000.rs b/src/bin/main.rs similarity index 69% rename from src/bin/onod3000.rs rename to src/bin/main.rs index 1ea1098..9abb034 100644 --- a/src/bin/onod3000.rs +++ b/src/bin/main.rs @@ -1,31 +1,3 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - -// This project is a Rust port of the original Java implementation by Paul Uszak. -// Original work is licensed under the terms specified in the respective file header. - - use std::fs::File; use std::io::{self, Read}; use std::path::Path; @@ -90,7 +62,7 @@ fn main() -> io::Result<()> { ("Runs", Onod::runs(&input_data)), ("RunUps", Onod::run_ups(&input_data)), ("Prediction", Onod::prediction(&input_data)), - ("UnCorrelation", Onod::uncorrelation(&input_data)), + ("UnCorrelation", Onod::un_correlation(&input_data)), ]; for (test_name, (observation, z_score, p_value)) in &tests { diff --git a/src/chisquaretest.rs b/src/chisquaretest.rs deleted file mode 100644 index 9d70a7e..0000000 --- a/src/chisquaretest.rs +++ /dev/null @@ -1,58 +0,0 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - -// This project is a Rust port of the original Java implementation by Paul Uszak. -// Original work is licensed under the terms specified in the respective file header. - - -use statrs::distribution::{ChiSquared, ContinuousCDF}; - -pub fn chi_square_test(observed: &[u64], expected: &[f64]) -> f64 { - // Preconditions - if observed.len() != expected.len() || observed.len() < 2 { - panic!("Observed and expected arrays must have the same length and length >= 2."); - } - if expected.iter().any(|&e| e <= 0.0) { - panic!("Expected array must contain only strictly positive values."); - } - - // Rescale expected array if necessary - let sum_observed: f64 = observed.iter().map(|&o| o as f64).sum(); - let sum_expected: f64 = expected.iter().sum(); - let rescaled_expected: Vec = expected.iter().map(|&e| e * sum_observed / sum_expected).collect(); - - // Calculate chi-squared statistic - let chi_squared_stat: f64 = observed - .iter() - .zip(rescaled_expected.iter()) - .map(|(&o, &e)| (o as f64 - e).powi(2) / e) - .sum(); - - // Perform chi-squared test - let degrees_of_freedom = observed.len() as f64 - 1.0; - let chi_squared_dist = ChiSquared::new(degrees_of_freedom).expect("Failed to create ChiSquared distribution"); - let p_value = 1.0 - chi_squared_dist.cdf(chi_squared_stat); - - p_value -} \ No newline at end of file diff --git a/src/ffi.rs b/src/ffi.rs deleted file mode 100644 index 0b3b513..0000000 --- a/src/ffi.rs +++ /dev/null @@ -1,71 +0,0 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - -// This project is a Rust port of the original Java implementation by Paul Uszak. -// Original work is licensed under the terms specified in the respective file header. - - -use std::ffi::{c_char, c_double, CStr}; - -use crate::Onod; - -#[no_mangle] -pub extern "C" fn onod_run( - test: *const c_char, - samples: *const u8, - len: usize, - result: *mut c_double, -) -> bool { - // Check for null pointers - if test.is_null() || samples.is_null() || result.is_null() { - eprintln!("Error: Null pointer passed to onod_run."); - return false; - } - - // Convert C string to Rust string - let test = unsafe { - match CStr::from_ptr(test).to_str() { - Ok(s) => s, - Err(_) => { - eprintln!("Error: Invalid UTF-8 string passed to onod_run."); - return false; - } - } - }; - - // Convert samples to a Rust slice - let samples = unsafe { std::slice::from_raw_parts(samples, len as usize) }; - - // Call the Rust `run` function - let (obs, z, p) = Onod::run(test, samples); - - // Write results to the output buffer - unsafe { - *result.offset(0) = obs; - *result.offset(1) = z; - *result.offset(2) = p; - } - - true -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a670d98..4d366df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,63 +1,3 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - -// This project is a Rust port of the original Java implementation by Paul Uszak. -// Original work is licensed under the terms specified in the respective file header. - - pub struct Onod; -mod uniformity; -pub mod chisquaretest; -pub mod well19937c; -pub mod ffi; -#[cfg(feature = "python")] -pub mod python; - -impl Onod { - pub fn run(test: &str, samples: &[u8]) -> (f64, f64, f64) { - - match test { - "avalanche" => Onod::avalanche(samples), - "chi_bit" => Onod::chi_bit(samples), - "chi_byte" => Onod::chi_byte(samples), - "compression" => Onod::compression(samples), - "gaps" => Onod::gaps(samples), - "ks" => Onod::ks(samples), - "mean_byte" => Onod::mean_byte(samples), - "monobit" => Onod::monobit(samples), - "pi" => Onod::pi(samples), - "prediction" => Onod::prediction(samples), - "runs" => Onod::runs(samples), - "run_ups" => Onod::run_ups(samples), - "shannon" => Onod::shannon(samples), - "shells" => Onod::shells(samples), - "uncorrelation" => Onod::uncorrelation(samples), - _ => { - eprintln!("Error: Unknown test '{}'", test); - (-1.0, 0.0, 0.0) - } - } - } -} \ No newline at end of file +mod uniformity; \ No newline at end of file diff --git a/src/python.rs b/src/python.rs deleted file mode 100644 index 699263c..0000000 --- a/src/python.rs +++ /dev/null @@ -1,47 +0,0 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - -// This project is a Rust port of the original Java implementation by Paul Uszak. -// Original work is licensed under the terms specified in the respective file header. - - -use pyo3::prelude::*; -use super::Onod as O; - -#[pyclass] -struct Onod; - -#[pymethods] -impl Onod { - #[staticmethod] - pub fn run(test: &str, samples: Vec) -> (f64, f64, f64) { - O::run(test, &samples) - } -} - -#[pymodule] -fn onod(m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_class::()?; - Ok(()) -} \ No newline at end of file diff --git a/src/uniformity/avalanche.rs b/src/uniformity/avalanche.rs index e878f53..5d62c9f 100644 --- a/src/uniformity/avalanche.rs +++ b/src/uniformity/avalanche.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/chi_bit.rs b/src/uniformity/chi_bit.rs index 220fbeb..777741c 100644 --- a/src/uniformity/chi_bit.rs +++ b/src/uniformity/chi_bit.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{ChiSquared, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/chi_byte.rs b/src/uniformity/chi_byte.rs index ddbb1f0..20b0a66 100644 --- a/src/uniformity/chi_byte.rs +++ b/src/uniformity/chi_byte.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use std::collections::HashMap; use statrs::distribution::{ChiSquared, ContinuousCDF}; diff --git a/src/uniformity/compression.rs b/src/uniformity/compression.rs index c1853dd..9c01de3 100644 --- a/src/uniformity/compression.rs +++ b/src/uniformity/compression.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use flate2::{write::DeflateEncoder, Compression}; use std::io::Write; use statrs::distribution::{Normal, ContinuousCDF}; diff --git a/src/uniformity/gaps.rs b/src/uniformity/gaps.rs index cf3328d..56057ae 100644 --- a/src/uniformity/gaps.rs +++ b/src/uniformity/gaps.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{ChiSquared, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/ks.rs b/src/uniformity/ks.rs index 9c76e9a..f786971 100644 --- a/src/uniformity/ks.rs +++ b/src/uniformity/ks.rs @@ -1,101 +1,47 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use kolmogorov_smirnov::test_f64; -use std::time::{SystemTime, UNIX_EPOCH}; -use statrs::distribution::ContinuousCDF; use crate::Onod; -use crate::well19937c::Well19937c; impl Onod { + /// KS randomness test - /// Performs the Kolmogorov-Smirnov test to evaluate the uniformity of data distribution - /// and returns the test statistic (D-statistic), z-score, and p-value. + /// Performs the Kolmogorov-Smirnov test to evaluate uniformity of data distribution and returns a p-value. + // Note: This implementation of the Kolmogorov-Smirnov (KS) test differs slightly from the + // Java implementation due to differences in library behavior and floating-point handling. + // The Java implementation (Apache Commons Math) adds random jitter to handle ties in small + // datasets, uses strict inequality for small sample sizes, and applies specific precision + // rules based on the IEEE 754 standard for `double`. The Rust implementation, using the + // `kolmogorov_smirnov` crate, does not add jitter or handle ties in the same way, and + // adheres to the crate's internal handling of floating-point comparisons. These differences + // may result in slight variations in p-values or KS statistics between the two versions. pub fn ks(samples: &[u8]) -> (f64, f64, f64) { + if samples.is_empty() { - return (-1.0, 0.0, 1.0); // Invalid input + return (-1.0, 0.0, 1.0); // empty data } - - // Normalize the input samples to [0, 1) range - let mut normalized_samples: Vec = samples.iter().map(|&x| x as f64 / 255.0).collect(); - + + // Normalize the input samples to [0, 1] range + let normalized_samples: Vec = samples.iter().map(|&x| x as f64 / 255.0).collect(); + // Generate a uniform distribution for comparison - let mut uniform_distribution: Vec = Self::generate_uniform_distribution(normalized_samples.len(), Self::get_timestamp_seed()); - - // Sort both distributions - normalized_samples.sort_by(|a, b| a.partial_cmp(b).unwrap()); - uniform_distribution.sort_by(|a, b| a.partial_cmp(b).unwrap()); - - let debug = false; - // Debugging: Optional print sorted values - if debug { - println!("Sorted Normalized Samples: {:?}", normalized_samples); - println!("Sorted Uniform Distribution: {:?}", uniform_distribution); - } - + let uniform_distribution: Vec = (0..normalized_samples.len()) + .map(|i| i as f64 / (normalized_samples.len() as f64 - 1.0)) + .collect(); + // Perform the Kolmogorov-Smirnov test - let confidence = 0.05; // Significance level + let confidence = 0.01; // Significance level let result = test_f64(&normalized_samples, &uniform_distribution, confidence); - + // Extract the KS statistic (D-statistic) let ks_statistic = result.statistic; - - // Debugging: Print ECDF differences and max difference (D-statistic) - if debug { - for (i, (&sample, &uniform)) in normalized_samples.iter().zip(&uniform_distribution).enumerate() { - let diff = (sample - uniform).abs(); - println!( - "Index: {}, Sample: {:.6}, Uniform: {:.6}, Difference: {:.6}", - i, sample, uniform, diff - ); - } - println!("D-Statistic: {:.6}", ks_statistic); - } - + // Calculate the z-score let sample_size = normalized_samples.len() as f64; let z_score = ks_statistic * sample_size.sqrt(); - - // Calculate the p-value - let p_value = 2.0 * (1.0 - statrs::distribution::Normal::new(0.0, 1.0).unwrap().cdf(z_score.abs())); - + + // Extract the p-value + let p_value = 1.0 - result.reject_probability; + (ks_statistic, z_score, p_value) } - - /// Generates a uniform distribution of the same length as the input data. - fn generate_uniform_distribution(len: usize, seed: u32) -> Vec { - let mut rng = Well19937c::new(seed); - (0..len).map(|_| rng.next_f64()).collect() - } - - fn get_timestamp_seed() -> u32 { - let duration = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - // Use seconds or nanoseconds as the seed - (duration.as_secs() as u32) ^ (duration.subsec_nanos()) - } } \ No newline at end of file diff --git a/src/uniformity/mean_byte.rs b/src/uniformity/mean_byte.rs index ff86b74..bcdf609 100644 --- a/src/uniformity/mean_byte.rs +++ b/src/uniformity/mean_byte.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/monobit.rs b/src/uniformity/monobit.rs index 4f81eff..c834a1e 100644 --- a/src/uniformity/monobit.rs +++ b/src/uniformity/monobit.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/pi.rs b/src/uniformity/pi.rs index 6db247e..a5a6058 100644 --- a/src/uniformity/pi.rs +++ b/src/uniformity/pi.rs @@ -1,82 +1,67 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - -/// Pi randomness test -/// Uses a Monte Carlo simulation to estimate randomness by calculating the approximation of Pi. - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; impl Onod { - /// Pi randomness test using nalgebra for vectorized operations. + + /// Pi randomness test + /// Uses a Monte Carlo simulation to estimate randomness by calculating the approximation of Pi. + /// This implementation of the Pi randomness test closely follows the logic of the original Java implementation. + /// However, minor differences in the results may arise due to the following reasons: + /// + /// 1. **Floating-Point Precision**: + /// Rust and Java both use 64-bit floating-point numbers (`double` in Java, `f64` in Rust), but slight differences + /// in their implementations (e.g., rounding modes, intermediate representations) can lead to small deviations. + /// + /// 2. **Math Libraries**: + /// Java uses Apache Commons Math for statistical computations, which may implement certain calculations + /// (e.g., Z-scores and normal distribution CDFs) differently compared to the `statrs` crate used in Rust. + /// + /// 3. **Bit Accuracy**: + /// The Java implementation notes the significance of bit accuracy in floating-point computations, + /// as defined in the IEEE 754 standard. Differences in handling edge cases (e.g., subnormal values, + /// precision limits) could lead to slight variations. + /// + /// These differences are generally negligible for practical purposes and do not affect the overall functionality or + /// statistical significance of the test. pub fn pi(samples: &[u8]) -> (f64, f64, f64) { - if samples.len() < 4 { - return (-1.0, 0.0, 1.0); // Not enough data - } - let normalized_samples: Vec = get_floats(samples); - - if normalized_samples.is_empty() { + if samples.is_empty() { return (-1.0, 0.0, 1.0); } - let mut sum_y = 0.0; - let count = normalized_samples.len() as f64; + // Normalize samples to [0.0, 1.0) + let normalized_samples: Vec = samples.iter().map(|&x| x as f64 / 255.0).collect(); + // Initialize variables for summary statistics + let mut sum_y = 0.0; + let mut count = 0.0; + + // Compute y-values (sqrt(1 - x^2)) and update summary statistics for &x in &normalized_samples { - let y = (1.0 - x.powi(2)).sqrt(); - sum_y += y as f64; + let y = (1.0 - x * x).sqrt(); + sum_y += y; + count += 1.0; } + // Calculate mean of y-values let mean_y = sum_y / count; + + // Calculate the test statistic let test_statistic = 4.0 * mean_y; - let variance = compute_variance(count); + + // Calculate variance and standard deviation + let variance = (16.0 / count) * ((2.0 / 3.0) - (std::f64::consts::PI / 4.0).powi(2)); let std_dev = variance.sqrt(); + + // Calculate Z-score let z_score = (test_statistic - std::f64::consts::PI) / std_dev; + // Use normal distribution to calculate p-value let normal_dist = Normal::new(0.0, 1.0).expect("Failed to create Normal distribution"); let p_value = 2.0 * (1.0 - normal_dist.cdf(z_score.abs())); (test_statistic, z_score, p_value) } - -} -fn get_floats(samples: &[u8]) -> Vec { - let mut floats = Vec::new(); - for chunk in samples.chunks_exact(4) { - let int_val = i32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); - let unsigned_val = (int_val as u32) >> 1; // Discard sign bit - let normalized = unsigned_val as f32 / i32::MAX as f32; - floats.push(normalized); - } - floats -} - -fn compute_variance(n: f64) -> f64 { - let term = (2.0 / 3.0) - (std::f64::consts::PI / 4.0).powi(2); - (16.0 / n) * term } \ No newline at end of file diff --git a/src/uniformity/prediction.rs b/src/uniformity/prediction.rs index c96a430..0dc8b65 100644 --- a/src/uniformity/prediction.rs +++ b/src/uniformity/prediction.rs @@ -1,91 +1,51 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - -use statrs::distribution::{ChiSquared, ContinuousCDF}; - -/* - * Blatantly copied from David Sexton's battery. - * - * An algorithm is used to predict the value of each byte of the sequence from - * the beginning of the sequence to the end. In a random sequence the - * probability of success of any such algorithm is 1/256. The number of successes - * is counted. A chi-squared statistic is calculated. The degrees-of-freedom is 1. - * The algorithm is as follows: the next byte is predicted to be equal to all the - * previous bytes bitwise XORed together. - */ +use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; impl Onod { + /// Prediction randomness test - /// Evaluates the predictability of the next byte based on XORing the previous bytes - /// and returns the total predictions, z-score, and p-value. + /// Evaluates the predictability of the next bit based on current data and returns a p-value. pub fn prediction(samples: &[u8]) -> (f64, f64, f64) { - if samples.len() < 3 { - return (-1.0, 0.0, 1.0); // Not enough data for meaningful calculation + + if samples.is_empty() { + return (-1.0, 0.0, 1.0); } let mut correct_predictions = 0; let mut total_predictions = 0; - let mut prediction = samples[0]; // Start with the first byte - for i in 2..samples.len() { - prediction ^= samples[i - 1]; // XOR all preceding bytes + for window in samples.windows(2) { + if let [current, next] = window { + let predicted = if current & 0x01 == 0 { 0 } else { 1 }; // Predict next bit based on LSB + let actual = next & 0x01; // Check LSB of the next byte - if prediction == samples[i] { - correct_predictions += 1; + if predicted == actual { + correct_predictions += 1; + } + + total_predictions += 1; } - total_predictions += 1; } - // Calculate expected and observed frequencies - let expected = vec![ - (1.0 / 256.0) * samples.len() as f64, // Probability of correct prediction - (255.0 / 256.0) * samples.len() as f64, // Probability of incorrect prediction - ]; - let observed = vec![ - correct_predictions as f64, // Actual correct predictions - (samples.len() - correct_predictions) as f64, // Actual incorrect predictions - ]; + if total_predictions == 0 { + return (-1.0, 0.0, 1.0); // No predictions possible + } - // Calculate chi-squared statistic - let chi_squared_stat: f64 = observed - .iter() - .zip(expected.iter()) - .map(|(o, e)| (o - e).powi(2) / e) - .sum(); + // Calculate observed proportion of correct predictions + let observed_proportion = correct_predictions as f64 / total_predictions as f64; - // Use Chi-Squared distribution to calculate p-value - let chi_squared_dist = ChiSquared::new(1.0).unwrap(); // Degrees of freedom = 1 - let p_value = 1.0 - chi_squared_dist.cdf(chi_squared_stat); + // Expected proportion for random data + let expected_proportion = 0.5; + let std_dev = (0.5 * 0.5 / total_predictions as f64).sqrt(); // Standard deviation for a binomial distribution - // Calculate z-score (optional, for diagnostics) - let mean = 1.0; // Mean of chi-squared distribution - let std_dev = (2.0 as f64).sqrt(); // Standard deviation of chi-squared distribution - let z_score = (chi_squared_stat - mean) / std_dev; + // Calculate the z-score + let z_score = (observed_proportion - expected_proportion) / std_dev; - (total_predictions as f64, z_score, p_value) + // Use normal distribution to calculate p-value + let normal_dist = Normal::new(0.0, 1.0).expect("Failed to create Normal distribution"); + let p_value = 2.0 * (1.0 - normal_dist.cdf(z_score.abs())); + + (observed_proportion, z_score, p_value) } -} +} \ No newline at end of file diff --git a/src/uniformity/runs.rs b/src/uniformity/runs.rs index f9ce524..a41d550 100644 --- a/src/uniformity/runs.rs +++ b/src/uniformity/runs.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/runups.rs b/src/uniformity/runups.rs index 6c71d45..3cf2624 100644 --- a/src/uniformity/runups.rs +++ b/src/uniformity/runups.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{ChiSquared, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/shannon.rs b/src/uniformity/shannon.rs index ab973ab..5d9cf77 100644 --- a/src/uniformity/shannon.rs +++ b/src/uniformity/shannon.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; diff --git a/src/uniformity/shells.rs b/src/uniformity/shells.rs index 01de0a7..5484e19 100644 --- a/src/uniformity/shells.rs +++ b/src/uniformity/shells.rs @@ -1,127 +1,101 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - +use statrs::distribution::{ChiSquared, ContinuousCDF}; use crate::Onod; -use crate::chisquaretest::chi_square_test; impl Onod { + /// Shells randomness test - /// Evaluates the uniformity of distances in a 3D sphere and returns the chi-squared statistic, z-score, and p-value. + /// Evaluates the uniformity of distances between identical byte values and returns a p-value. pub fn shells(input: &[u8]) -> (f64, f64, f64) { - + // Define shell radii (precomputed to ensure equal volumes) const SHELL_RADII: [f64; 35] = [ - 1., 0.990384019787941, 0.980577593308067, - 0.970571001281035, 0.960353705642329, 0.949914251592996, - 0.939240154232372, 0.928317766722556, 0.91713212619864, - 0.905666772691187, 0.893903535096568, 0.881822276616739, - 0.869400589952457, 0.856613429672063, 0.843432665301749, - 0.829826533366243, 0.815758959214771, 0.801188709029197, - 0.786068317431936, 0.770342714221672, 0.753947441129154, - 0.736806299728077, 0.718828193851318, 0.699902804775202, - 0.67989452969576, 0.65863375600835, 0.635903899768996, - 0.61142141746576, 0.584803547642573, 0.555513224287824, - 0.52275795857471, 0.485285500640517, 0.440911138308369, - 0.385171357110836, 0.30571070873288, + 1., 0.990384019787941, 0.980577593308067, 0.970571001281035, 0.960353705642329, + 0.949914251592996, 0.939240154232372, 0.928317766722556, 0.91713212619864, + 0.905666772691187, 0.893903535096568, 0.881822276616739, 0.869400589952457, + 0.856613429672063, 0.843432665301749, 0.829826533366243, 0.815758959214771, + 0.801188709029197, 0.786068317431936, 0.770342714221672, 0.753947441129154, + 0.736806299728077, 0.718828193851318, 0.699902804775202, 0.67989452969576, + 0.65863375600835, 0.635903899768996, 0.61142141746576, 0.584803547642573, + 0.555513224287824, 0.52275795857471, 0.485285500640517, 0.440911138308369, + 0.385171357110836, 0.30571070873288 ]; - let samples = convert_to_3d_points(&input); + let samples = convert_to_3d_points(input); + + if samples.len() < 25000 { + // eprintln!("---------------------------------------------------------------"); + // eprintln!("ERROR: Shells test requires at least 25,000 points for statistical validity. Skipping."); + // eprintln!("---------------------------------------------------------------"); + return (-1.0, 0.0, 1.0); // Skip the test for small datasets + } + let sphere_radius = SHELL_RADII[0]; - let num_shells = SHELL_RADII.len(); - - // Calculate sphere and cube proportions + let no_shells = SHELL_RADII.len(); + + // Calculate sphere and cube volume proportions let cube_side = 2.0 * sphere_radius; let cube_volume = cube_side.powi(3); let sphere_volume = (4.0 / 3.0) * std::f64::consts::PI * sphere_radius.powi(3); - let sphere_proportion = sphere_volume / cube_volume; - - let num_points = samples.len() as f64; - let num_points_per_shell = sphere_proportion * num_points / num_shells as f64; - - // Initialize observed and expected frequencies - let mut observed = vec![0u64; num_shells]; - let expected: Vec = vec![num_points_per_shell; num_shells]; - - // Assign points to shells + let sphere_proportion = sphere_volume / cube_volume; // Theoretical value: π/6 + + let no_points = samples.len() as f64; + let no_points_per_shell = sphere_proportion * no_points / no_shells as f64; + + let mut observed = vec![0u64; no_shells]; + let expected: Vec = vec![no_points_per_shell; no_shells]; + for (x, y, z) in samples { + // Compute radius from origin let radius = (x.powi(2) + y.powi(2) + z.powi(2)).sqrt(); - - // Skip points outside the sphere + + // Ignore points outside the sphere if radius > sphere_radius { continue; } - - for j in 1..num_shells { + + // Assign to the correct shell + for j in 1..SHELL_RADII.len() { if radius > SHELL_RADII[j] { observed[j - 1] += 1; break; } } - - // Assign to the last shell if radius <= SHELL_RADII[num_shells - 1] - if radius < SHELL_RADII[num_shells - 1] { - observed[num_shells - 1] += 1; + + if radius < SHELL_RADII[no_shells - 1] { + observed[no_shells - 1] += 1; } - } - - // Calculate chi-squared statistic - let chi_squared_stat: f64 = observed - .iter() + + // Perform Chi-Square Test + let chi_squared_stat: f64 = observed.iter() .zip(expected.iter()) .map(|(&o, &e)| (o as f64 - e).powi(2) / e) .sum(); - - // Perform chi-squared test - let degrees_of_freedom = num_shells as f64 - 1.0; - let p_value = chi_square_test(&observed, &expected); - - // Calculate z-score - let mean = degrees_of_freedom; - let std_dev = (2.0 * degrees_of_freedom).sqrt(); + + let degrees_of_freedom = no_shells as f64 - 1.0; + let chi_squared_dist = ChiSquared::new(degrees_of_freedom).expect("Failed to create ChiSquared distribution"); + let p_value = 1.0 - chi_squared_dist.cdf(chi_squared_stat); + + // Z-score calculation (standardization of the chi-squared statistic) + let mean = degrees_of_freedom; // Mean of the chi-squared distribution + let std_dev = (2.0 * degrees_of_freedom).sqrt(); // Standard deviation of the chi-squared distribution let z_score = (chi_squared_stat - mean) / std_dev; - // Return the results (chi_squared_stat, z_score, p_value) - } + } } fn convert_to_3d_points(data: &[u8]) -> Vec<(f64, f64, f64)> { let mut points = Vec::new(); - for chunk in data.chunks(12) { - if chunk.len() == 12 { - let x = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) >> 1; - let y = u32::from_be_bytes([chunk[4], chunk[5], chunk[6], chunk[7]]) >> 1; - let z = u32::from_be_bytes([chunk[8], chunk[9], chunk[10], chunk[11]]) >> 1; - - points.push(( - x as f64 / (i32::MAX as f64), - y as f64 / (i32::MAX as f64), - z as f64 / (i32::MAX as f64), - )); + for chunk in data.chunks(3) { + if chunk.len() == 3 { + // Normalize the bytes to [0.0, 1.0) range + let x = chunk[0] as f64 / 255.0; + let y = chunk[1] as f64 / 255.0; + let z = chunk[2] as f64 / 255.0; + points.push((x, y, z)); } } diff --git a/src/uniformity/uncorrelation.rs b/src/uniformity/uncorrelation.rs index 506f738..40a94fe 100644 --- a/src/uniformity/uncorrelation.rs +++ b/src/uniformity/uncorrelation.rs @@ -1,28 +1,3 @@ -// This file is a Rust port of the original Java implementation by Paul Uszak. -// Original Java code: -// http://www.reallyreallyrandom.com/gitbucketlabhub/ -// -// Copyright (c) 2023 Paul Uszak. Port (C) 2025 by Tobias Raayoni Last (@randogoth) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - - use statrs::distribution::{Normal, ContinuousCDF}; use crate::Onod; @@ -31,7 +6,7 @@ impl Onod { /// UnCorrelation randomness test /// Computes the Pearson correlation between the sequence and its shifted version, returning a p-value. - pub fn uncorrelation(input: &[u8]) -> (f64, f64, f64) { + pub fn un_correlation(input: &[u8]) -> (f64, f64, f64) { let samples = input.iter().map(|&x| x as i32).collect::>(); diff --git a/src/well19937c.rs b/src/well19937c.rs deleted file mode 100644 index c1e3b6b..0000000 --- a/src/well19937c.rs +++ /dev/null @@ -1,87 +0,0 @@ -// MIT License - -// Copyright (c) 2025 Tobias Raayoni Last (@randogoth) - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// --- - - -pub struct Well19937c { - state: [u32; 624], - index: usize, -} - -impl Well19937c { - /// Creates a new instance of Well19937c with a given seed. - pub fn new(seed: u32) -> Self { - let mut state = [0u32; 624]; - state[0] = seed; - - for i in 1..624 { - state[i] = 1812433253u32 - .wrapping_mul(state[i - 1] ^ (state[i - 1] >> 30)) - .wrapping_add(i as u32); - } - - Well19937c { state, index: 0 } - } - - /// Updates the internal state. - fn twist(&mut self) { - const M: usize = 397; - const MATRIX_A: u32 = 0x9908b0df; // Constant matrix A - const UPPER_MASK: u32 = 0x80000000; // Most significant w-r bits - const LOWER_MASK: u32 = 0x7fffffff; // Least significant r bits - - for i in 0..624 { - let x = (self.state[i] & UPPER_MASK) + (self.state[(i + 1) % 624] & LOWER_MASK); - let mut x_a = x >> 1; - - if x % 2 != 0 { - x_a ^= MATRIX_A; - } - - self.state[i] = self.state[(i + M) % 624] ^ x_a; - } - - self.index = 0; - } - - /// Generates the next random number in the sequence. - pub fn next_u32(&mut self) -> u32 { - if self.index == 0 { - self.twist(); - } - - let mut y = self.state[self.index]; - self.index = (self.index + 1) % 624; - - // Matsumoto-Kurita tempering - y ^= (y << 7) & 0xe46e1700; - y ^= (y << 15) & 0x9b868000; - - y - } - - /// Generates the next random `f64` in [0, 1). - pub fn next_f64(&mut self) -> f64 { - self.next_u32() as f64 / u32::MAX as f64 - } -} \ No newline at end of file diff --git a/test/test1.bin b/test/test1.bin deleted file mode 100644 index 8b39050..0000000 Binary files a/test/test1.bin and /dev/null differ diff --git a/test/test2.bin b/test/test2.bin deleted file mode 100644 index 93578e1..0000000 Binary files a/test/test2.bin and /dev/null differ diff --git a/test/test3.bin b/test/test3.bin deleted file mode 100644 index 91b946c..0000000 Binary files a/test/test3.bin and /dev/null differ