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 a simple monobit test.
|
||||
- Added a block frequency test.
|
||||
|
||||
[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"
|
||||
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]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
|
@ -139,6 +148,7 @@ name = "rand_testsuite"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"extra-math",
|
||||
"libm",
|
||||
"num-traits",
|
||||
"rand",
|
||||
|
|
22
Cargo.nix
22
Cargo.nix
|
@ -22,7 +22,7 @@ args @ {
|
|||
workspaceSrc,
|
||||
ignoreLockHash,
|
||||
}: let
|
||||
nixifiedLockHash = "0c97699175df8652eb6708b342caa7bcc3794d5a6bd83ecc4362d8cf3b262349";
|
||||
nixifiedLockHash = "a2b590ebe54f290db87e552bf935f4bb11098b9ba02841e8ed499aad10c57419";
|
||||
workspaceSrc =
|
||||
if args.workspaceSrc == null
|
||||
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 {
|
||||
name = "funty";
|
||||
version = "2.0.0";
|
||||
|
@ -332,6 +351,7 @@ in
|
|||
];
|
||||
dependencies = {
|
||||
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;
|
||||
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]
|
||||
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"
|
||||
num-traits = { version = "0.2.19", default-features = false, features = [
|
||||
"libm",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! All supported tests are available in this module.
|
||||
|
||||
mod block_frequency;
|
||||
mod monobit;
|
||||
|
||||
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