Skip to content
Snippets Groups Projects
Commit eed3372e authored by Mathis "what could possibly go wrong" Randl's avatar Mathis "what could possibly go wrong" Randl
Browse files

randomized test generation using quickcheck

parent be75ef8f
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,127 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "env_logger"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"log",
"regex",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
version = "0.2.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "proximity"
version = "0.1.0"
dependencies = [
"quickcheck",
]
[[package]]
name = "quickcheck"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
dependencies = [
"env_logger",
"log",
"rand",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
......@@ -4,3 +4,6 @@ version = "0.1.0"
edition = "2021"
[dependencies]
[dev-dependencies]
quickcheck = "1.0.3"
......@@ -7,14 +7,19 @@ impl<'a> Vector<'a> {
self._repr.len()
}
/// Computes the **SQUARED** L2 distance between two vectors. This is cheaper to compute than the regular L2 distance. This is typically useful when comparing two distances : dist(u,v) < dist(w, x) <=> dist(u,v) ** 2 < dist(w,x) ** 2
/// # Usage
/// Computes the **SQUARED** L2 distance between two vectors.
/// This is cheaper to compute than the regular L2 distance.
/// This is typically useful when comparing two distances :
///
/// dist(u,v) < dist(w, x) ⇔ dist(u,v) ** 2 < dist(w,x) ** 2
///
/// # Panics
///
/// Panics in debug mode if the two vectors have different lengths. In release mode, the longest vector will
/// be silently truncated.
/// Panics in debug mode if the two vectors have different lengths.
/// In release mode, the longest vector will be silently truncated.
#[inline]
pub fn l2_dist_square(&self, other: &Vector<'a>) -> f32 {
pub fn l2_dist_squared(&self, other: &Vector<'a>) -> f32 {
debug_assert!(self.len() == other.len());
self._repr
......@@ -27,9 +32,16 @@ impl<'a> Vector<'a> {
.sum::<f32>()
}
/// # Usage
/// Computes the L2 distance between two vectors.
///
/// # Panics
///
/// Panics in debug mode if the two vectors have different lengths.
/// In release mode, the longest vector will be silently truncated.
#[inline]
pub fn l2_dist(&self, other: &Vector<'a>) -> f32 {
self.l2_dist_square(other).sqrt()
self.l2_dist_squared(other).sqrt()
}
}
......@@ -42,6 +54,7 @@ impl<'a> From<&'a [f32]> for Vector<'a> {
#[cfg(test)]
mod tests {
use super::*;
use quickcheck::{QuickCheck, TestResult};
const TOLERANCE: f32 = 1e-8;
......@@ -49,15 +62,27 @@ mod tests {
(target - actual).abs() < TOLERANCE
}
fn check_l2(suspect: f32) -> bool {
fn is_valid_l2(suspect: f32) -> bool {
suspect.is_finite() && suspect >= 0.0
}
#[test]
fn self_sim_is_zero() {
let testvec = Vector::from([1.0, 2.0, 3.0, 1.5].as_slice());
let selfsim = testvec.l2_dist(&testvec);
assert!(check_l2(selfsim));
assert!(close(selfsim, 0.0));
fn qc_self_sim_is_zero(totest: Vec<f32>) -> TestResult {
if totest.iter().any(|x| !x.is_finite()) {
return TestResult::discard();
}
let testvec = Vector::from(&totest[..]);
let selfsim = testvec.l2_dist(&testvec);
let to_check = is_valid_l2(selfsim) && close(selfsim, 0.0);
return TestResult::from_bool(to_check);
}
QuickCheck::new()
.tests(10_000)
// force that less than 90% of tests are discarded due to precondition violations
// i.e. at least 10% of inputs should be valid so that we cover a good range
.min_tests_passed(1_000)
.quickcheck(qc_self_sim_is_zero as fn(Vec<f32>) -> TestResult);
}
}
#![allow(dead_code)]
mod linalg;
fn main() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment