use half::{bf16, f16};
use proptest::prelude::*;
use proptest::test_runner::{Config, TestCaseResult, TestRunner};
use std::ops::Range;
const CASES_PER_DIMENSION_SHARD: u32 = 16;
const MIN_TEST_DIMENSION: usize = 4;
const MAX_TEST_DIMENSION: usize = 4048;
const NUM_DIMENSION_SHARDS: usize = 16;
pub fn dimension_shard(shard: usize) -> Range<usize> {
let dimensions_per_shard = (MAX_TEST_DIMENSION - MIN_TEST_DIMENSION) / NUM_DIMENSION_SHARDS;
let start = MIN_TEST_DIMENSION + shard * dimensions_per_shard;
let end = if shard + 1 == NUM_DIMENSION_SHARDS {
MAX_TEST_DIMENSION
} else {
start + dimensions_per_shard
};
start..end
}
pub fn arbitrary_f16() -> impl Strategy<Value = f16> {
any::<u16>().prop_map(|bits| {
let val = f16::from_bits(bits);
if val.is_infinite() && val.is_sign_positive() {
f16::MAX
} else if val.is_infinite() && val.is_sign_negative() {
f16::MIN
} else if val.is_nan() {
f16::from_f32(0.0)
} else {
val
}
})
}
pub fn arbitrary_bf16() -> impl Strategy<Value = bf16> {
any::<u16>()
.prop_map(|bits| {
let val = bf16::from_bits(bits);
if val.is_infinite() && val.is_sign_positive() {
bf16::MAX
} else if val.is_infinite() && val.is_sign_negative() {
bf16::MIN
} else if val.is_nan() {
bf16::from_f32(0.0)
} else {
val
}
})
.prop_map(|val: bf16| {
let scaling = bf16::from_f32(1e12 / f32::MAX);
val * scaling
})
}
pub fn arbitrary_f32() -> impl Strategy<Value = f32> {
use proptest::num::f32::*;
let scaling = 1e12 / f32::MAX;
(NORMAL | SUBNORMAL | POSITIVE | NEGATIVE).prop_map(move |val: f32| val * scaling)
}
pub fn arbitrary_f64() -> impl Strategy<Value = f64> {
use proptest::num::f64::*;
let scaling = 1e12 / f64::MAX;
(NORMAL | SUBNORMAL | POSITIVE | NEGATIVE).prop_map(move |val: f64| val * scaling)
}
pub fn arbitrary_vector_pair<T: std::fmt::Debug, S>(
values: impl Fn() -> S + 'static,
dim_range: std::ops::Range<usize>,
) -> impl Strategy<Value = (Vec<T>, Vec<T>)>
where
S: Strategy<Value = T>,
{
dim_range.prop_flat_map(move |dim| {
let x = prop::collection::vec(values(), dim);
let y = prop::collection::vec(values(), dim);
(x, y)
})
}
pub fn run_vector_pair_proptest<T, S, F>(values: fn() -> S, dim_range: Range<usize>, property: F)
where
T: std::fmt::Debug,
S: Strategy<Value = T> + 'static,
F: Fn(Vec<T>, Vec<T>) -> TestCaseResult,
{
let strategy = arbitrary_vector_pair(values, dim_range);
let mut runner = TestRunner::new(Config {
cases: CASES_PER_DIMENSION_SHARD,
..Config::default()
});
runner.run(&strategy, |(x, y)| property(x, y)).unwrap();
}
pub fn run_vector_proptest<T, S, F>(values: fn() -> S, dim_range: Range<usize>, property: F)
where
T: std::fmt::Debug,
S: Strategy<Value = T>,
F: Fn(Vec<T>) -> TestCaseResult,
{
let strategy = prop::collection::vec(values(), dim_range);
let mut runner = TestRunner::new(Config {
cases: CASES_PER_DIMENSION_SHARD,
..Config::default()
});
runner.run(&strategy, property).unwrap();
}