Deterministic transcendental functions (exp, log, tanh, sinh, cosh) #
IEEE-754 fixes the representation and the basic arithmetic operations, but it does not mandate
exact bit-level behavior for transcendental functions like exp and log. In practice, libraries
(libm, SVML, CUDA math, etc.) make slightly different choices, and results can differ across
platforms.
In TorchLean, we still need executable transcendental operations in some examples and runtime
experiments. So we give IEEE32Exec deterministic definitions for a small set of functions using
fixed algorithms:
exp: range reduction + a fixed-point polynomial for $2^{x/\log 2}$,log: normalization $x=m2^k$ + a convergent atanh-series for $\log m$,sinh,cosh: defined viaexp,tanh: a small-input odd polynomial plus a bounded expression in terms ofexp.
Here we prove the special-value rules for those definitions: how NaNs, infinities, signed
zeros (+0 and -0), and sign checks behave. These are the facts we want in proofs without
unfolding the full fixed-point
implementations.
We do not claim that the finite-value approximations match any particular hardware expf/logf;
the Lean definitions prioritize reproducibility and well-defined behavior.
Finite approximation contracts #
The deterministic functions in this module have proved special-value behavior below. A numerical accuracy claim on finite inputs requires a separate contract. Keeping that evidence explicit prevents reproducible execution from being mistaken for correct rounding.
A uniform real-error contract for an executable unary binary32 operation on a stated domain.
For every finite input whose real value lies in domain, the executable result must also be finite
and differ from spec by at most tolerance.
Instances For
A proved approximation contract remains valid when its tolerance is weakened.
exp #
Special values we follow (common libm / PyTorch behavior):
- $\exp(\mathrm{NaN})=\mathrm{NaN}$ (we quiet signaling NaNs),
- $\exp(+\infty)=+\infty$,
- $\exp(-\infty)=+0$.
For finite inputs, Exec32.lean defines a deterministic approximation. These lemmas only expose
the early "special-case" branches, so proofs do not have to unfold the fixed-point core.
exp propagates NaNs by returning the quieted NaN payload.
log #
The special cases match the usual real-analytic extension used by common libraries:
- $\log(\mathrm{NaN})=\mathrm{NaN}$ (quieted),
- $\log(+\infty)=+\infty$,
- $\log(0)=-\infty$ (for both $+0$ and $-0$),
- $\log(x)=\mathrm{NaN}$ for $x<0$ (including $\log(-\infty)$).
PyTorch follows these conventions on IEEE hardware; we mirror them in IEEE32Exec.log.
log propagates NaNs by returning the quieted NaN payload.
$\log(-\infty)=\mathrm{NaN}$ (domain error for negative inputs).
log returns canonicalNaN on negative finite inputs (domain error).
This captures the standard real domain restriction $\log:(0,+\infty)\to\mathbb{R}$, transported to the float32 setting (excluding NaNs, infinities, and zeros, which are handled by earlier branches).
tanh #
Special values we follow:
- $\tanh(\mathrm{NaN})=\mathrm{NaN}$ (quieted),
- $\tanh(+\infty)=+1$,
- $\tanh(-\infty)=-1$.
The bit patterns used below are the IEEE-754 binary32 encodings of +1.0f and -1.0f:
0x3F800000represents $+1$,0xBF800000represents $-1$.
tanh propagates NaNs by returning the quieted NaN payload (via chooseNaN1).
sinh / cosh #
These are defined in Exec32.lean in terms of exp (with a NaN short-circuit up front), so the
special cases are the familiar ones:
- propagate NaNs (quieted),
- $\sinh(\pm\infty)=\pm\infty$,
- $\cosh(\pm\infty)=+\infty$.
sinh propagates NaNs by returning the quieted NaN payload (via chooseNaN1).
cosh propagates NaNs by returning the quieted NaN payload (via chooseNaN1).