TorchLean API

NN.Floats.FP32.Error

FP32 per-op error bounds #

Proofs about numerical code should not have to expand the definition of “float32 rounding” every time they use + or exp. This file provides reusable rewrite theorems for FP32 rounding-error reasoning.

We collect those lemmas for TorchLean’s FP32 model:

This mirrors the standard mental model behind PyTorch/IEEE float analysis (even though our proof backend is not a bit-level model): it’s the classic “real computation + rounding error” split.

The pattern is always:

Important nuance: these are local statements about a single rounding step. Whole-network bounds typically combine these with:

References #

This module works with a proof-friendly float32 semantics ("real operation + one rounding step"). Relating this abstraction to specific hardware/libm behavior is a separate, target-specific trust boundary handled elsewhere in TorchLean.

Per-op rounding error lemmas #

Core rounding lemma for the binary32 parameters fixed by FP32.

This is the “one thing we use everywhere”: once you know an operation is defined as “round the real result”, the proof goal reduces to an instance of this lemma.

Informal: if fl32(x) denotes rounding x : ℝ to the binary32 grid, then |fl32(x) - x| ≤ eps₃₂(x).

Addition: FP32 adds in and then rounds once.

This lemma isolates the rounding error introduced by that last step.

Informal: |fl32(a+b) - (a+b)| ≤ eps₃₂(a+b).

Subtraction: one real subtraction followed by one rounding step.

Informal: |fl32(a-b) - (a-b)| ≤ eps₃₂(a-b).

Multiplication: one real multiplication followed by one rounding step.

Informal: |fl32(a*b) - (a*b)| ≤ eps₃₂(a*b).

Division: one real division followed by one rounding step.

This does not say division is “well-conditioned”; it only isolates the rounding stage.

Informal: |fl32(a/b) - (a/b)| ≤ eps₃₂(a/b).

Transcendentals (proof semantics) #

In FP32, transcendental functions are specified as: apply the real function, then round.

That is not how hardware/libm is implemented, but it is exactly the right abstraction for proofs: it gives a clear mathematical meaning and a one-rounding-step error theorem.

Informal: |fl32(exp(x)) - exp(x)| ≤ eps₃₂(exp(x)), and similarly for the other functions below.

tanh in the proof model: real tanh followed by rounding.

Informal: |fl32(tanh(x)) - tanh(x)| ≤ eps₃₂(tanh(x)).

log in the proof model: real log followed by rounding.

Domain note: the inequality is about rounding error around Real.log a.val; it does not assert anything about a.val > 0.

Informal: |fl32(log(x)) - log(x)| ≤ eps₃₂(log(x)).

cos in the proof model: real cos followed by rounding.

Informal: |fl32(cos(x)) - cos(x)| ≤ eps₃₂(cos(x)).

sin in the proof model: real sin followed by rounding.

Informal: |fl32(sin(x)) - sin(x)| ≤ eps₃₂(sin(x)).

sinh in the proof model: real sinh followed by rounding.

Informal: |fl32(sinh(x)) - sinh(x)| ≤ eps₃₂(sinh(x)).

cosh in the proof model: real cosh followed by rounding.

Informal: |fl32(cosh(x)) - cosh(x)| ≤ eps₃₂(cosh(x)).

sqrt in the proof model: real sqrt followed by rounding.

Informal: |fl32(sqrt(x)) - sqrt(x)| ≤ eps₃₂(sqrt(x)).

abs in the proof model: real absolute value followed by rounding.

Even though |x| is exact over , we still round the result because this is a “round after every primitive” semantics.

Informal: |fl32(|x|) - |x|| ≤ eps₃₂(|x|).