#![allow(clippy::undocumented_unsafe_blocks)]
use crate::gf;
use crate::tables::TABLE_BYTES;
#[kani::proof]
fn gf_mul_is_commutative() {
let a: u8 = kani::any();
let b: u8 = kani::any();
assert_eq!(gf::mul(a, b), gf::mul(b, a));
}
#[kani::proof]
fn gf_mul_identity_and_zero() {
let a: u8 = kani::any();
assert_eq!(gf::mul(a, 1), a);
assert_eq!(gf::mul(a, 0), 0);
assert_eq!(gf::mul(0, a), 0);
}
#[kani::proof]
fn gf_inverse_inverts() {
let a: u8 = kani::any();
kani::assume(a != 0);
assert_eq!(gf::mul(a, gf::inv(a)), 1);
}
#[kani::proof]
#[kani::unwind(9)]
fn gf_table_and_shift_multiplies_agree() {
let a: u8 = kani::any();
let b: u8 = kani::any();
assert_eq!(gf::mul(a, b), gf::mul_shift(a, b));
}
#[kani::proof]
fn dimension_check_arithmetic_cannot_overflow() {
let k: usize = kani::any();
let p: usize = kani::any();
let accepted = k != 0 && p != 0 && k.checked_add(p).is_some_and(|m| m <= 255);
if accepted {
assert!(k <= 255 && p <= 255);
assert!(k + p <= 255);
} else {
assert!(k == 0 || p == 0 || k > 255 || p > 255 || k + p > 255 || k > usize::MAX - p);
}
}
#[kani::proof]
#[kani::unwind(6)]
fn matrix_construction_never_panics_bounded() {
let k: usize = kani::any();
let p: usize = kani::any();
kani::assume(k <= 4 && p <= 4);
let _ = crate::Matrix::reed_solomon(k, p);
let _ = crate::Matrix::cauchy(k, p);
}
#[kani::proof]
fn nibble_table_offsets_stay_in_bounds() {
let rows: usize = kani::any();
let k: usize = kani::any();
let r: usize = kani::any();
let j: usize = kani::any();
kani::assume(rows >= 1 && rows <= 8);
kani::assume(k >= 1 && k <= 32);
kani::assume(r < rows);
kani::assume(j < k);
let len = rows * k * TABLE_BYTES; let start = (r * k + j) * TABLE_BYTES;
assert!(start < len);
assert!(start + TABLE_BYTES <= len);
assert!(start + 16 + 16 <= len);
}
#[kani::proof]
fn affine_table_offsets_stay_in_bounds() {
const AFFINE_BYTES: usize = 8;
let rows: usize = kani::any();
let k: usize = kani::any();
let r: usize = kani::any();
let j: usize = kani::any();
kani::assume(rows >= 1 && rows <= 8);
kani::assume(k >= 1 && k <= 32);
kani::assume(r < rows);
kani::assume(j < k);
let len = rows * k * AFFINE_BYTES;
let start = (r * k + j) * AFFINE_BYTES;
assert!(start + AFFINE_BYTES <= len);
}
#[kani::proof]
fn table_mul_indices_are_in_range() {
let x: u8 = kani::any();
let lo = (x & 0x0f) as usize;
let hi = 16 + (x >> 4) as usize;
assert!(lo < TABLE_BYTES);
assert!(hi < TABLE_BYTES);
}
#[kani::proof]
fn chunked_loop_never_reads_past_end() {
let n: usize = kani::any();
let i: usize = kani::any();
let step: usize = kani::any();
kani::assume(n <= usize::MAX / 2);
kani::assume(i <= usize::MAX / 2);
kani::assume(step == 16 || step == 32 || step == 64 || step == 128);
kani::assume(i + step <= n);
assert!(i < n);
assert!(i + step <= n);
assert!(n - (i + step) < n);
}