generated from ProcyOS/rust-template
add block frequency test
This commit is contained in:
parent
b56d1b1314
commit
badc11aac5
6 changed files with 99 additions and 1 deletions
|
@ -9,5 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Added a simple monobit test.
|
- Added a simple monobit test.
|
||||||
|
- Added a block frequency test.
|
||||||
|
|
||||||
[Unreleased]: https://git.chir.rs/ProcyOS/rand_testsuite
|
[Unreleased]: https://git.chir.rs/ProcyOS/rand_testsuite
|
||||||
|
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -32,6 +32,15 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "extra-math"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://git.chir.rs/ProcyOS/extra_math.git#38d6abf85718d053f45c6b77c88607f245be55e0"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -139,6 +148,7 @@ name = "rand_testsuite"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec",
|
||||||
|
"extra-math",
|
||||||
"libm",
|
"libm",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand",
|
"rand",
|
||||||
|
|
22
Cargo.nix
22
Cargo.nix
|
@ -22,7 +22,7 @@ args @ {
|
||||||
workspaceSrc,
|
workspaceSrc,
|
||||||
ignoreLockHash,
|
ignoreLockHash,
|
||||||
}: let
|
}: let
|
||||||
nixifiedLockHash = "0c97699175df8652eb6708b342caa7bcc3794d5a6bd83ecc4362d8cf3b262349";
|
nixifiedLockHash = "a2b590ebe54f290db87e552bf935f4bb11098b9ba02841e8ed499aad10c57419";
|
||||||
workspaceSrc =
|
workspaceSrc =
|
||||||
if args.workspaceSrc == null
|
if args.workspaceSrc == null
|
||||||
then ./.
|
then ./.
|
||||||
|
@ -113,6 +113,25 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
"git+https://git.chir.rs/ProcyOS/extra_math.git".extra-math."0.1.0" = overridableMkRustCrate (profileName: rec {
|
||||||
|
name = "extra-math";
|
||||||
|
version = "0.1.0";
|
||||||
|
registry = "git+https://git.chir.rs/ProcyOS/extra_math.git";
|
||||||
|
src = fetchCrateGit {
|
||||||
|
url = "https://git.chir.rs/ProcyOS/extra_math.git";
|
||||||
|
name = "extra-math";
|
||||||
|
version = "0.1.0";
|
||||||
|
rev = "38d6abf85718d053f45c6b77c88607f245be55e0";
|
||||||
|
};
|
||||||
|
features = builtins.concatLists [
|
||||||
|
["default"]
|
||||||
|
];
|
||||||
|
dependencies = {
|
||||||
|
libm = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libm."0.2.8" {inherit profileName;}).out;
|
||||||
|
num_traits = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".num-traits."0.2.19" {inherit profileName;}).out;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".funty."2.0.0" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".funty."2.0.0" = overridableMkRustCrate (profileName: rec {
|
||||||
name = "funty";
|
name = "funty";
|
||||||
version = "2.0.0";
|
version = "2.0.0";
|
||||||
|
@ -332,6 +351,7 @@ in
|
||||||
];
|
];
|
||||||
dependencies = {
|
dependencies = {
|
||||||
bitvec = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitvec."1.0.1" {inherit profileName;}).out;
|
bitvec = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".bitvec."1.0.1" {inherit profileName;}).out;
|
||||||
|
extra_math = (rustPackages."git+https://git.chir.rs/ProcyOS/extra_math.git".extra-math."0.1.0" {inherit profileName;}).out;
|
||||||
libm = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libm."0.2.8" {inherit profileName;}).out;
|
libm = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".libm."0.2.8" {inherit profileName;}).out;
|
||||||
num_traits = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".num-traits."0.2.19" {inherit profileName;}).out;
|
num_traits = (rustPackages."registry+https://github.com/rust-lang/crates.io-index".num-traits."0.2.19" {inherit profileName;}).out;
|
||||||
${
|
${
|
||||||
|
|
|
@ -11,6 +11,7 @@ categories = ["development-tools::testing", "no-std", "no-std::no-alloc"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitvec = { version = "1.0.1", default-features = false }
|
bitvec = { version = "1.0.1", default-features = false }
|
||||||
|
extra-math = { git = "https://git.chir.rs/ProcyOS/extra_math.git", version = "0.1.0" }
|
||||||
libm = "0.2.8"
|
libm = "0.2.8"
|
||||||
num-traits = { version = "0.2.19", default-features = false, features = [
|
num-traits = { version = "0.2.19", default-features = false, features = [
|
||||||
"libm",
|
"libm",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! All supported tests are available in this module.
|
//! All supported tests are available in this module.
|
||||||
|
|
||||||
|
mod block_frequency;
|
||||||
mod monobit;
|
mod monobit;
|
||||||
|
|
||||||
use bitvec::prelude::{BitOrder, BitSlice, BitStore};
|
use bitvec::prelude::{BitOrder, BitSlice, BitStore};
|
||||||
|
|
65
src/tests/block_frequency.rs
Normal file
65
src/tests/block_frequency.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
//! Block Frequency Test
|
||||||
|
|
||||||
|
use bitvec::prelude::{BitOrder, BitSlice, BitStore};
|
||||||
|
use extra_math::gamma::Gamma;
|
||||||
|
#[allow(unused_imports, reason = "redundant in std use cases")]
|
||||||
|
use num_traits::Float;
|
||||||
|
|
||||||
|
use crate::RandomTest;
|
||||||
|
|
||||||
|
/// The Block Frequency Test splits the input data into multiple blocks, counts the frequency 1s and 0s within these blocks, and determines whether these are distributed well.
|
||||||
|
///
|
||||||
|
/// The amount of blocks is chosen such that a block is at least 1% of the size of the total input, or at least 20.
|
||||||
|
///
|
||||||
|
/// This test is defined in the [NIST Special Publication 800-22](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-22r1a.pdf).
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct BlockFrequency;
|
||||||
|
|
||||||
|
impl RandomTest for BlockFrequency {
|
||||||
|
const RECOMMENDED_BIT_SIZE: usize = 100;
|
||||||
|
|
||||||
|
const MINIMUM_BIT_SIZE: usize = 0;
|
||||||
|
|
||||||
|
fn evaluate<T: BitStore, O: BitOrder>(&self, bs: &BitSlice<T, O>) -> Option<f64> {
|
||||||
|
let block_size = (bs.len() / 100).max(20);
|
||||||
|
let block_count = bs.len() / block_size;
|
||||||
|
let mut statistic = 0.0;
|
||||||
|
for i in 0..block_count {
|
||||||
|
let one_count: usize = bs[i * block_size..(i + 1) * block_size]
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| if *v { 1 } else { 0 })
|
||||||
|
.sum();
|
||||||
|
let pi = (one_count as f64) / (block_size as f64);
|
||||||
|
statistic += (pi - 0.5).powi(2);
|
||||||
|
}
|
||||||
|
statistic *= (4 * block_size) as f64;
|
||||||
|
Some(Gamma::upper_gamma_regularized(
|
||||||
|
block_size as f64 / 2.0,
|
||||||
|
statistic / 2.0,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use bitvec::prelude::*;
|
||||||
|
|
||||||
|
use crate::RandomTest;
|
||||||
|
|
||||||
|
use super::BlockFrequency;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_frequency_test_vector() {
|
||||||
|
let epsilon = bitvec![
|
||||||
|
1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1,
|
||||||
|
0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0
|
||||||
|
];
|
||||||
|
let res = BlockFrequency.evaluate(epsilon.as_bitslice());
|
||||||
|
assert!(res.is_some());
|
||||||
|
let res = res.unwrap();
|
||||||
|
assert!(res > 0.01, "Data should be evaluated as random");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue