use super::*;
#[test]
fn falsify_cv_001_output_shape() {
let test_cases: Vec<(usize, usize, usize, usize, usize, usize, usize)> = vec![
(1, 1, 3, 1, 0, 10, 8), (4, 8, 5, 1, 0, 20, 16), (4, 8, 3, 2, 0, 10, 4), (4, 8, 3, 1, 1, 10, 10), (1, 1, 1, 1, 0, 5, 5), ];
for (i, &(ic, oc, k, s, p, l_in, l_out)) in test_cases.iter().enumerate() {
let conv = Conv1d::with_options(ic, oc, k, s, p, true);
let x = Tensor::ones(&[2, ic, l_in]);
let y = conv.forward(&x);
assert_eq!(
y.shape(),
&[2, oc, l_out],
"FALSIFIED CV-001 case {i}: shape {:?}, expected [2, {oc}, {l_out}]",
y.shape()
);
}
}
#[test]
fn falsify_cv_001b_shape_formula() {
for k in [1, 3, 5] {
for s in [1, 2] {
for p in [0, 1] {
let l_in = 20;
let expected_l_out = (l_in + 2 * p - k) / s + 1;
let conv = Conv1d::with_options(2, 4, k, s, p, false);
let x = Tensor::ones(&[1, 2, l_in]);
let y = conv.forward(&x);
assert_eq!(
y.shape()[2],
expected_l_out,
"FALSIFIED CV-001b: K={k}, S={s}, P={p}: L_out={}, expected {expected_l_out}",
y.shape()[2]
);
}
}
}
}
#[test]
fn falsify_cv_005_kernel_one() {
let conv = Conv1d::new(4, 8, 1);
let x = Tensor::ones(&[2, 4, 15]);
let y = conv.forward(&x);
assert_eq!(
y.shape(),
&[2, 8, 15],
"FALSIFIED CV-005: K=1 should preserve spatial dimension"
);
}
#[test]
fn falsify_cv_002_linearity_no_bias() {
let conv = Conv1d::with_options(2, 3, 3, 1, 0, false);
let x = Tensor::new(
&(0..2 * 2 * 8)
.map(|i| (i as f32 * 0.1).sin())
.collect::<Vec<_>>(),
&[2, 2, 8],
);
let y_base = conv.forward(&x);
for &alpha in &[2.0_f32, 0.5, -1.0, 0.1] {
let scaled_data: Vec<f32> = x.data().iter().map(|&v| v * alpha).collect();
let x_scaled = Tensor::new(&scaled_data, x.shape());
let y_scaled = conv.forward(&x_scaled);
for (i, (&ys, &yb)) in y_scaled.data().iter().zip(y_base.data().iter()).enumerate() {
let expected = alpha * yb;
let diff = (ys - expected).abs();
let tol = 1e-3 * expected.abs().max(1.0);
assert!(
diff < tol,
"FALSIFIED CV-002: conv({alpha}*x)[{i}] = {ys}, expected {expected}, diff = {diff}"
);
}
}
}
mod conv1d_proptest_falsify {
use super::*;
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(50))]
#[test]
fn falsify_cv_001_prop_output_shape(
k in prop::sample::select(vec![1usize, 3, 5, 7]),
s in prop::sample::select(vec![1usize, 2]),
p in prop::sample::select(vec![0usize, 1]),
l_in in 10..=50usize,
) {
let in_ch = 2;
let out_ch = 4;
if l_in + 2 * p >= k {
let expected = (l_in + 2 * p - k) / s + 1;
let conv = Conv1d::with_options(in_ch, out_ch, k, s, p, false);
let x = Tensor::ones(&[1, in_ch, l_in]);
let y = conv.forward(&x);
prop_assert_eq!(
y.shape()[2],
expected,
"FALSIFIED CV-001-prop: K={}, S={}, P={}, L_in={}: L_out={}, expected={}",
k, s, p, l_in, y.shape()[2], expected
);
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(30))]
#[test]
fn falsify_cv_005_prop_kernel_one(
l_in in 1..=100usize,
) {
let conv = Conv1d::new(2, 4, 1);
let x = Tensor::ones(&[1, 2, l_in]);
let y = conv.forward(&x);
prop_assert_eq!(
y.shape()[2],
l_in,
"FALSIFIED CV-005-prop: K=1, L_in={}, L_out={}",
l_in, y.shape()[2]
);
}
}
}