use crate::fkc::verify::bit_stability::{
HostTensor, KernelInvoker, ProbeInputs, VerifyError, VerifyOutcome,
};
use crate::kernel::BindingEntry;
use fuel_graph::jit::{OpTag, PatternNode};
use fuel_ir::DType;
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
pub(crate) fn ulp_distance(x: f32, y: f32) -> u64 {
u64::from(kiss_ref_core::ulp_distance_f32(x, y))
}
#[derive(Debug, Clone, Copy)]
#[allow(clippy::enum_variant_names)]
pub enum Bound {
MaxUlp(u32),
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
MaxRelative(f64),
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
MaxAbsolute(f64),
}
#[derive(Debug, Clone, Copy)]
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
struct Elem {
key: i128,
value: f64,
is_nan: bool,
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
fn key16(bits: u16) -> i128 {
if bits & 0x8000 != 0 {
-i128::from(bits & 0x7FFF)
} else {
i128::from(bits)
}
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
fn key32(bits: u32) -> i128 {
if bits & 0x8000_0000 != 0 {
-i128::from(bits & 0x7FFF_FFFF)
} else {
i128::from(bits)
}
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
fn key64(bits: u64) -> i128 {
if bits & 0x8000_0000_0000_0000 != 0 {
-i128::from(bits & 0x7FFF_FFFF_FFFF_FFFF)
} else {
i128::from(bits)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
enum CompareMode {
UlpFloat,
ExactInt,
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
fn compare_mode(dt: DType) -> Option<(CompareMode, usize)> {
Some(match dt {
DType::F8E4M3 => (CompareMode::UlpFloat, 1),
DType::F16 | DType::BF16 => (CompareMode::UlpFloat, 2),
DType::F32 => (CompareMode::UlpFloat, 4),
DType::F64 => (CompareMode::UlpFloat, 8),
DType::Bool | DType::U8 => (CompareMode::ExactInt, 1),
DType::I8 => (CompareMode::ExactInt, 1),
DType::I16 => (CompareMode::ExactInt, 2),
DType::U32 | DType::I32 => (CompareMode::ExactInt, 4),
DType::I64 => (CompareMode::ExactInt, 8),
_ => return None,
})
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
fn elem_at(dt: DType, bytes: &[u8], i: usize, width: usize) -> Option<Elem> {
let b = bytes.get(i * width..(i + 1) * width)?;
Some(match dt {
DType::F8E4M3 => {
let bits = b[0];
Elem {
key: if bits & 0x80 != 0 {
-i128::from(bits & 0x7F)
} else {
i128::from(bits)
},
value: super::exact_ref::f8e4m3_decode(bits),
is_nan: (bits & 0x7F) == 0x7F,
}
}
DType::F16 => {
let bits = u16::from_le_bytes([b[0], b[1]]);
Elem {
key: key16(bits),
value: f64::from(half::f16::from_bits(bits).to_f32()),
is_nan: (bits & 0x7C00) == 0x7C00 && (bits & 0x03FF) != 0,
}
}
DType::BF16 => {
let bits = u16::from_le_bytes([b[0], b[1]]);
Elem {
key: key16(bits),
value: f64::from(half::bf16::from_bits(bits).to_f32()),
is_nan: (bits & 0x7F80) == 0x7F80 && (bits & 0x007F) != 0,
}
}
DType::F32 => {
let bits = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
Elem {
key: key32(bits),
value: f64::from(f32::from_bits(bits)),
is_nan: f32::from_bits(bits).is_nan(),
}
}
DType::F64 => {
let mut a = [0u8; 8];
a.copy_from_slice(b);
let bits = u64::from_le_bytes(a);
Elem {
key: key64(bits),
value: f64::from_bits(bits),
is_nan: f64::from_bits(bits).is_nan(),
}
}
DType::Bool | DType::U8 => Elem {
key: i128::from(b[0]),
value: f64::from(b[0]),
is_nan: false,
},
DType::I8 => Elem {
key: i128::from(b[0] as i8),
value: f64::from(b[0] as i8),
is_nan: false,
},
DType::I16 => {
let v = i16::from_le_bytes([b[0], b[1]]);
Elem {
key: i128::from(v),
value: f64::from(v),
is_nan: false,
}
}
DType::U32 => {
let v = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
Elem {
key: i128::from(v),
value: f64::from(v),
is_nan: false,
}
}
DType::I32 => {
let v = i32::from_le_bytes([b[0], b[1], b[2], b[3]]);
Elem {
key: i128::from(v),
value: f64::from(v),
is_nan: false,
}
}
DType::I64 => {
let mut a = [0u8; 8];
a.copy_from_slice(b);
let v = i64::from_le_bytes(a);
Elem {
key: i128::from(v),
value: v as f64,
is_nan: false,
}
}
_ => return None,
})
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
pub fn verify_precision_bound(
cand: &dyn KernelInvoker,
refr: &dyn KernelInvoker,
entry: &BindingEntry,
probes: &[ProbeInputs],
bound: Bound,
) -> Result<VerifyOutcome, VerifyError> {
for (probe_idx, probe) in probes.iter().enumerate() {
let a: HostTensor = cand.invoke(entry, probe)?;
let b: HostTensor = refr.invoke(entry, probe)?;
if a.dtype != b.dtype {
return Ok(VerifyOutcome::Fail {
detail: format!(
"probe {probe_idx}: candidate dtype {:?} != reference dtype {:?} — a comparison across dtypes is not a precision measurement",
a.dtype, b.dtype
),
});
}
let Some((mode, width)) = compare_mode(a.dtype) else {
return Ok(VerifyOutcome::Fail {
detail: format!(
"probe {probe_idx}: no comparison implemented for output dtype {:?} — refused rather than approximated in another dtype's space",
a.dtype
),
});
};
if a.bytes.len() != b.bytes.len() {
return Ok(VerifyOutcome::Fail {
detail: format!(
"probe {probe_idx}: candidate is {} bytes, reference {} — lengths must match or the comparison silently covers only a prefix",
a.bytes.len(),
b.bytes.len()
),
});
}
if !a.bytes.len().is_multiple_of(width) {
return Ok(VerifyOutcome::Fail {
detail: format!(
"probe {probe_idx}: {} bytes is not a whole number of {:?} elements",
a.bytes.len(),
a.dtype
),
});
}
if mode == CompareMode::ExactInt && matches!(bound, Bound::MaxUlp(_)) {
if let Some(i) = a.bytes.iter().zip(b.bytes.iter()).position(|(x, y)| x != y) {
return Ok(VerifyOutcome::Fail {
detail: format!(
"probe {probe_idx} byte {i}: candidate {:#04x} vs reference {:#04x} — {:?} outputs must be bit-exact, and {bound:?} on an integer dtype IS a bit-exactness claim",
a.bytes[i], b.bytes[i], a.dtype
),
});
}
continue;
}
let n = a.bytes.len() / width;
for i in 0..n {
let (Some(x), Some(y)) = (
elem_at(a.dtype, &a.bytes, i, width),
elem_at(b.dtype, &b.bytes, i, width),
) else {
return Ok(VerifyOutcome::Fail {
detail: format!("probe {probe_idx} elem {i}: could not decode {:?}", a.dtype),
});
};
let dist: u64 = if x.is_nan && y.is_nan {
0
} else if x.is_nan || y.is_nan {
u64::MAX
} else {
let d = (x.key - y.key).unsigned_abs();
if d > u128::from(u64::MAX) {
u64::MAX
} else {
d as u64
}
};
let ok = match bound {
Bound::MaxUlp(m) => dist <= u64::from(m),
Bound::MaxAbsolute(m) => !(x.is_nan || y.is_nan) && (x.value - y.value).abs() <= m,
Bound::MaxRelative(m) => {
let denom = y.value.abs().max(f64::from(f32::EPSILON));
!(x.is_nan || y.is_nan) && ((x.value - y.value).abs() / denom) <= m
}
};
if !ok {
let detail = match bound {
Bound::MaxUlp(_) => format!(
"probe {probe_idx} elem {i}: {:?} candidate {:02x?} ({}) vs reference {:02x?} ({}) are {dist} ULP apart, exceeds {bound:?}",
a.dtype,
&a.bytes[i * width..(i + 1) * width],
x.value,
&b.bytes[i * width..(i + 1) * width],
y.value,
),
_ => format!(
"probe {probe_idx} elem {i}: {:?} candidate {} vs reference {} exceeds {bound:?}",
a.dtype, x.value, y.value
),
};
return Ok(VerifyOutcome::Fail { detail });
}
}
}
Ok(VerifyOutcome::Pass)
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
pub(crate) fn is_transcendental(tag: OpTag) -> bool {
use OpTag::*;
matches!(
tag,
Exp | Log | Sin | Cos | Tanh | Sigmoid | Silu | GeluTanh | Gelu | Erf | Rsqrt
)
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
pub fn region_contains_transcendental(region: &PatternNode) -> bool {
match region {
PatternNode::Op { op, operands, .. } => {
is_transcendental(*op) || operands.iter().any(region_contains_transcendental)
}
PatternNode::SeeThrough { then } => region_contains_transcendental(then),
PatternNode::Bind { .. } | PatternNode::Any => false,
}
}
#[allow(
dead_code,
reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
)]
pub fn widen_bound_for_transcendental(bound: Bound) -> Bound {
match bound {
Bound::MaxUlp(m) => Bound::MaxUlp(m.saturating_mul(2)),
Bound::MaxRelative(m) => Bound::MaxRelative(m * 2.0),
Bound::MaxAbsolute(m) => Bound::MaxAbsolute(m * 2.0),
}
}
#[cfg(test)]
mod tests {
use super::{
Bound, is_transcendental, region_contains_transcendental, ulp_distance,
widen_bound_for_transcendental,
};
use fuel_graph::jit::{OpAttrs, OpTag, PatternNode};
#[test]
fn f16_outputs_are_compared_in_f16_space_not_widened_to_f32() {
use super::{Bound, verify_precision_bound};
use crate::fkc::verify::bit_stability::{
HostTensor, KernelInvoker, VerifyError, VerifyOutcome,
};
use crate::kernel::BindingEntry;
struct ConstInvoker(Vec<u8>);
impl KernelInvoker for ConstInvoker {
fn invoke(
&self,
_entry: &BindingEntry,
_inputs: &[HostTensor],
) -> Result<HostTensor, VerifyError> {
Ok(HostTensor {
dtype: fuel_ir::DType::F16,
shape: vec![4],
bytes: self.0.clone(),
})
}
}
let ones: Vec<u8> = (0..4)
.flat_map(|_| half::f16::from_f32(1.0).to_le_bytes())
.collect();
let twos: Vec<u8> = (0..4)
.flat_map(|_| half::f16::from_f32(2.0).to_le_bytes())
.collect();
assert_eq!(
ones.len(),
8,
"4 x f16 is 8 bytes — the length the old %4 guard let through"
);
let entry = BindingEntry {
kernel: crate::dispatch::add_elementwise_f32_cpu_wrapper,
caps: crate::kernel::KernelCaps::empty(),
precision: crate::fused::PrecisionGuarantee::UNAUDITED,
cost: crate::kernel::unknown_cost,
kernel_source: "test",
is_generic: false,
kernel_revision_hash: 0,
cost_expr: None,
};
let probes = vec![vec![]];
let inside = verify_precision_bound(
&ConstInvoker(ones.clone()),
&ConstInvoker(twos.clone()),
&entry,
&probes,
Bound::MaxUlp(1024),
)
.expect("no infrastructure error");
assert!(
matches!(inside, VerifyOutcome::Pass),
"1.0f16 and 2.0f16 are exactly 1024 f16-ULP apart and must pass a \
1024 bound; got {inside:?}"
);
let outside = verify_precision_bound(
&ConstInvoker(ones.clone()),
&ConstInvoker(twos.clone()),
&entry,
&probes,
Bound::MaxUlp(1023),
)
.expect("no infrastructure error");
match outside {
VerifyOutcome::Fail { detail } => assert!(
detail.contains("1024 ULP apart"),
"expected the true f16 distance of 1024 in the report; got: {detail}"
),
other => panic!(
"1.0f16 vs 2.0f16 must exceed a 1023 bound; got {other:?}. A Pass here \
is a fabricated agreement, which is worse than a wrong number."
),
}
let same = verify_precision_bound(
&ConstInvoker(ones.clone()),
&ConstInvoker(ones),
&entry,
&probes,
Bound::MaxUlp(0),
)
.expect("no infrastructure error");
assert!(
matches!(same, VerifyOutcome::Pass),
"identical f16 buffers must be 0 ULP apart; got {same:?}"
);
}
#[test]
fn integer_outputs_compare_exactly_rather_than_in_ulp_space() {
use super::{Bound, verify_precision_bound};
use crate::fkc::verify::bit_stability::{
HostTensor, KernelInvoker, VerifyError, VerifyOutcome,
};
use crate::kernel::BindingEntry;
struct I8Invoker(Vec<u8>);
impl KernelInvoker for I8Invoker {
fn invoke(
&self,
_entry: &BindingEntry,
_inputs: &[HostTensor],
) -> Result<HostTensor, VerifyError> {
Ok(HostTensor {
dtype: fuel_ir::DType::I8,
shape: vec![4],
bytes: self.0.clone(),
})
}
}
let entry = BindingEntry {
kernel: crate::dispatch::add_elementwise_f32_cpu_wrapper,
caps: crate::kernel::KernelCaps::empty(),
precision: crate::fused::PrecisionGuarantee::UNAUDITED,
cost: crate::kernel::unknown_cost,
kernel_source: "test",
is_generic: false,
kernel_revision_hash: 0,
cost_expr: None,
};
let probes = vec![vec![]];
let a = vec![1u8, 2, 3, 4];
let b = vec![1u8, 2, 3, 5];
let out = verify_precision_bound(
&I8Invoker(a.clone()),
&I8Invoker(b),
&entry,
&probes,
Bound::MaxUlp(u32::MAX),
)
.expect("no infrastructure error");
match out {
VerifyOutcome::Fail { detail } => assert!(
detail.contains("bit-exact"),
"expected the failure to say integers are compared bit-exactly; got: {detail}"
),
other => panic!(
"a differing I8 byte must fail even an unbounded ULP claim; got {other:?} — \
a generous bound must not launder an integer mismatch"
),
}
let same = verify_precision_bound(
&I8Invoker(a.clone()),
&I8Invoker(a),
&entry,
&probes,
Bound::MaxUlp(0),
)
.expect("no infrastructure error");
assert!(
matches!(same, VerifyOutcome::Pass),
"identical I8 buffers must pass; got {same:?}"
);
}
#[test]
fn an_unimplemented_output_dtype_is_refused_by_name() {
use super::{Bound, verify_precision_bound};
use crate::fkc::verify::bit_stability::{
HostTensor, KernelInvoker, VerifyError, VerifyOutcome,
};
use crate::kernel::BindingEntry;
struct F8Invoker;
impl KernelInvoker for F8Invoker {
fn invoke(
&self,
_entry: &BindingEntry,
_inputs: &[HostTensor],
) -> Result<HostTensor, VerifyError> {
Ok(HostTensor {
dtype: fuel_ir::DType::F8E5M2,
shape: vec![4],
bytes: vec![0x30, 0x31, 0x32, 0x33],
})
}
}
let entry = BindingEntry {
kernel: crate::dispatch::add_elementwise_f32_cpu_wrapper,
caps: crate::kernel::KernelCaps::empty(),
precision: crate::fused::PrecisionGuarantee::UNAUDITED,
cost: crate::kernel::unknown_cost,
kernel_source: "test",
is_generic: false,
kernel_revision_hash: 0,
cost_expr: None,
};
let out =
verify_precision_bound(&F8Invoker, &F8Invoker, &entry, &[vec![]], Bound::MaxUlp(0))
.expect("no infrastructure error");
match out {
VerifyOutcome::Fail { detail } => {
assert!(
detail.contains("F8E5M2") && detail.contains("refused"),
"the refusal must NAME the dtype it refused; got: {detail}"
);
}
other => panic!(
"two IDENTICAL F8E5M2 buffers returned {other:?}. A Pass here is the \
defect: it would be a verdict produced without an implemented \
comparison, and identical inputs are exactly how such a verdict \
looks correct."
),
}
}
#[test]
fn widen_doubles_each_bound() {
assert!(matches!(
widen_bound_for_transcendental(Bound::MaxUlp(4)),
Bound::MaxUlp(8)
));
match widen_bound_for_transcendental(Bound::MaxRelative(1e-6)) {
Bound::MaxRelative(m) => assert!((m - 2e-6).abs() < 1e-18),
other => panic!("expected MaxRelative, got {other:?}"),
}
match widen_bound_for_transcendental(Bound::MaxAbsolute(0.25)) {
Bound::MaxAbsolute(m) => assert_eq!(m, 0.5),
other => panic!("expected MaxAbsolute, got {other:?}"),
}
assert!(matches!(
widen_bound_for_transcendental(Bound::MaxUlp(u32::MAX)),
Bound::MaxUlp(u32::MAX)
));
}
#[test]
fn is_transcendental_classifies_exactly() {
for t in [
OpTag::Exp,
OpTag::Log,
OpTag::Sin,
OpTag::Cos,
OpTag::Tanh,
OpTag::Sigmoid,
OpTag::Silu,
OpTag::GeluTanh,
OpTag::Gelu,
OpTag::Erf,
OpTag::Rsqrt,
] {
assert!(is_transcendental(t), "{t:?} should be transcendental");
}
for t in [
OpTag::Sqrt,
OpTag::Recip,
OpTag::Relu,
OpTag::Neg,
OpTag::Abs,
OpTag::Sqr,
] {
assert!(!is_transcendental(t), "{t:?} should NOT be transcendental");
}
}
#[test]
fn region_transcendental_detection_walks_nested() {
let inner = PatternNode::Op {
op: OpTag::Exp,
operands: vec![PatternNode::Bind { index: 0 }],
attrs: OpAttrs::default(),
};
let outer = PatternNode::Op {
op: OpTag::Neg,
operands: vec![inner],
attrs: OpAttrs::default(),
};
assert!(
region_contains_transcendental(&outer),
"nested Exp must be found"
);
let inner2 = PatternNode::Op {
op: OpTag::Sqr,
operands: vec![PatternNode::Bind { index: 0 }],
attrs: OpAttrs::default(),
};
let outer2 = PatternNode::Op {
op: OpTag::Neg,
operands: vec![inner2],
attrs: OpAttrs::default(),
};
assert!(
!region_contains_transcendental(&outer2),
"no transcendental atom present"
);
}
#[test]
fn ulp_distance_signed_zero_is_one() {
assert_eq!(ulp_distance(-0.0, 0.0), 1);
assert_eq!(ulp_distance(0.0, -0.0), 1);
}
#[test]
fn ulp_distance_same_value_is_zero() {
assert_eq!(ulp_distance(1.0, 1.0), 0);
assert_eq!(ulp_distance(-3.5, -3.5), 0);
}
#[test]
fn ulp_distance_adjacent_same_sign_is_one() {
let a = 1.0_f32;
let b = f32::from_bits(a.to_bits() + 1); assert_eq!(ulp_distance(a, b), 1);
let c = -1.0_f32;
let d = f32::from_bits(c.to_bits() + 1); assert_eq!(ulp_distance(c, d), 1);
}
#[test]
fn ulp_distance_straddling_zero_is_small() {
let pos_min = f32::from_bits(1); let neg_min = f32::from_bits(0x8000_0001); assert_eq!(ulp_distance(pos_min, neg_min), 3);
}
#[test]
fn ulp_distance_nan_handling_matches_kiss_ref() {
assert_eq!(ulp_distance(f32::NAN, 1.0), u64::from(u32::MAX));
assert_eq!(ulp_distance(1.0, f32::NAN), u64::from(u32::MAX));
assert_eq!(ulp_distance(f32::NAN, f32::NAN), 0);
}
}