Bridging FP32 error bounds into ≈[t] #
NN.Proofs.RuntimeApprox.Core.Tolerance defines a small “close enough” relation:
approxR x y t(notation:x ≈[t] y)
Here we connect that generic notion of tolerance to our FP32 rounding model.
In NN.Floats.FP32.Error we prove per‑operation absolute error bounds like
abs (approx - exact) ≤ eps₃₂ exact
We repackage those bounds so downstream proofs can use the uniform ≈[t] vocabulary.
Two small conventions show up everywhere below:
We use an absolute-only tolerance
ApproxTol.absOnly eps. That meansx ≈[absOnly eps] yis literally the usual bound|y - x| ≤ eps(seeapproxR_absOnly_iff). This matches the shape of ourFP32theorems.The
FP32“epsilon” is value-dependent:eps = ulp(exact) / 2 = eps₃₂(exact). This is the standard round-to-nearest error model: the ulp is smaller near 0 and grows as the magnitude grows. Writing it as an≈[t]fact makes it easy to mix with other tolerances without inventing yet another approximation relation.
The next two lemmas are local rewrite helpers:
approxR_absOnly_of_abs_sub_leturns a plainabs (y - x) ≤ epsinequality into anapproxR.eps32_nonnegis the nonnegativity proof we need to useapproxR_absOnly_iff.
They are private because they are only used by this file's approximation bridge.
Arithmetic (one real op + one rounding step) #
FP32 addition, stated as an ≈[t] fact with t = absOnly (ulp(exact)/2).
Read this as:
- “the exact real sum” is
a.val + b.val, - “the rounded result” is
(a + b).val, - and the two differ by at most half an ulp of the exact real sum.
Informal: a.val + b.val ≈[absOnly (eps₃₂(a.val + b.val))] (a + b).val.
FP32 subtraction, stated as an ≈[t] fact with t = absOnly (eps₃₂(exact)).
Informal: a.val - b.val ≈[absOnly (eps₃₂(a.val - b.val))] (a - b).val.
FP32 multiplication, stated as an ≈[t] fact with t = absOnly (eps₃₂(exact)).
Informal: a.val * b.val ≈[absOnly (eps₃₂(a.val * b.val))] (a * b).val.
FP32 division, stated as an ≈[t] fact with t = absOnly (eps₃₂(exact)).
Informal: a.val / b.val ≈[absOnly (eps₃₂(a.val / b.val))] (a / b).val.
Transcendentals (real function + rounding) #
FP32 exp is Real.exp followed by rounding; this is the result as an ≈[t] statement.
Informal: exp(a.val) ≈[absOnly (eps₃₂(exp(a.val)))] (exp a).val.
FP32 tanh as an ≈[t] statement.
Informal: tanh(a.val) ≈[absOnly (eps₃₂(tanh(a.val)))] (tanh a).val.
FP32 log as an ≈[t] statement (using Real.log as the exact reference).
Informal: log(a.val) ≈[absOnly (eps₃₂(log(a.val)))] (log a).val.
FP32 cos as an ≈[t] statement.
Informal: cos(a.val) ≈[absOnly (eps₃₂(cos(a.val)))] (cos a).val.
FP32 sin as an ≈[t] statement.
Informal: sin(a.val) ≈[absOnly (eps₃₂(sin(a.val)))] (sin a).val.
FP32 sinh as an ≈[t] statement.
Informal: sinh(a.val) ≈[absOnly (eps₃₂(sinh(a.val)))] (sinh a).val.
FP32 cosh as an ≈[t] statement.
Informal: cosh(a.val) ≈[absOnly (eps₃₂(cosh(a.val)))] (cosh a).val.
FP32 sqrt as an ≈[t] statement.
Informal: sqrt(a.val) ≈[absOnly (eps₃₂(sqrt(a.val)))] (sqrt a).val.
FP32 abs as an ≈[t] statement.
Informal: |a.val| ≈[absOnly (eps₃₂(|a.val|))] (abs a).val.