The softmax bug that started it¶
A few weeks ago, Jon Barron shared a post about two numerical bugs in softmax and cross-entropy, based on work with Dan Gnanapragasam and Michael Tschannen. I went back to TorchLean and checked our own softmax implementation. Funny enough, it had the same problem: in float32, the target gradient became zero even though the true answer was nonzero and representable. We'd already proved the formula correct over the real numbers, but as Edward Yang pointed out, that didn't establish its floating-point accuracy. I wanted to know what else we were missing.
FloatLib lets us model the floating-point arithmetic directly and prove error or sign bounds for the formulas we execute. Blanchard and the Highams studied softmax and log-sum-exp in detail, and Prieto and collaborators had already identified Softmax Collapse. I wanted to bring that analysis into TorchLean, compare the library calls, and try different formulas where we found failures.
Now, the fundamental operators¶
After discussing softmax with Sasha, we decided to look at more of the fundamental operators : ) An operator is one of the building blocks of a neural network: addition, matrix multiplication, an activation, normalization, or a loss. These are the calls we combine when we build a model in PyTorch or JAX. The mathematical specification tells us what each operator should compute. The implementation also chooses the precision of intermediate values, the order of additions, and when to round. So the same operator can give different answers in different libraries, even with the same mathematical definition.
We examined all 154 TorchLean operators, or 162 entries when variants are counted separately. We have executable Lean rules for 159 entries; erf, erf-based GELU, and custom are not covered by that executable sweep. We compared the matching operations wherever available in PyTorch, JAX, TensorFlow, NumPy, CuPy, ONNX Runtime, and MLX, with CPU and GPU measurements kept separate. The main comparison spans several commonly used precisions and roughly 780 million outputs. Later, we take selected original and rewritten formulas through 526 different formats using FloatLib. The study combines executable Lean specifications, machine-checked proofs, and cross-library comparisons.1
| Family | Entries | Operators and variants |
|---|---|---|
| Arithmetic | 18 | add, sub, mul, div, div floor, div trunc, addcmul, addcdiv, lerp, neg, abs, square, reciprocal, scale, fmod, remainder, copysign, nextafter |
| Roots and powers | 6 | sqrt, sqrt clampNeg, rsqrt, cbrt, pow, hypot |
| Rounding to integers | 6 | floor, ceil, round, trunc, frac, sign |
| Exponentials and logarithms | 7 | exp, exp2, expm1, log, log2, log10, log1p |
| Trigonometric and hyperbolic | 13 | sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh |
| Activations | 9 | relu, leakyReLU, elu, sigmoid, softplus, silu, gelu (tanh), gelu (erf), erf |
| Guarded operations | 6 | safeLog, safeInv, safeDiv, smoothAbs, nanToNum, clamp |
| Comparisons and selection | 14 | max, min, fmax, fmin, eq, ne, lt, le, gt, ge, isNaN, isInf, isFinite, select |
| Reductions, scans and sorting | 15 | reduce sum, reduce prod, reduce max, reduce min, mean, cumsum, cumprod, cummax, cummin, argmax, argmin, sort, sort desc, topk, topKMask |
| Softmax and losses | 14 | softmax, logSoftmax, maskedSoftmax, crossEntropy, crossEntropyProbs, binaryCrossEntropy, mseLoss, maeLoss, huberLoss, hingeLoss, poissonLoss, logCoshLoss, cosineLoss, distill |
| Layers | 13 | linear, matmul, scaledMatmul, contract, conv, convTranspose, pool, smoothMaxPool, layerNorm, batchNorm, batchNormRunning, embedding, dropout |
| Attention, scans and transforms | 6 | attention, attnFromScores, multiheadAttn, selectiveScan, rfft, irfft |
| Movement and indexing | 17 | detach, reshape, permute, broadcast, fullLike, flip, slice, pad, cat, gather, scatter, indexAt, indices, encodeIndex, decodeIndex, cast, bitcast |
| Logic, bits and integers | 14 | logicalNot, logicalAnd, logicalOr, logicalXor, bitwiseAnd, bitwiseOr, bitwiseXor, bitwiseNot, bitwiseLeftShift, shiftRightArith, shiftRightLogical, populationCount, countLeadZeros, mulhi |
| Random | 3 | randUniform, randn, bernoulliMask |
| No rule | 1 | custom |
Preliminaries¶
In Lean Verified Precision, Sasha discussed why a formula that is right over the reals can still behave badly in floating point. Here, let's start with how we're measuring error. A floating-point format represents only certain numbers; the gap between two neighboring numbers at a given magnitude is one unit in the last place, or ULP. Immediately above 1 in float32:
\[ \begin{aligned} \text{next value}&=1+2^{-23}\\ &\approx1.0000001192,\\[3pt] \text{gap}&=2^{-23}\approx1.19\times10^{-7}. \end{aligned} \]
That spacing changes with the magnitude of the number, so a ULP is not a fixed tolerance. When I write zero ULPs in a table, I mean the result agrees with the exact mathematical answer rounded once to the chosen format; one ULP means the result is one representable step away. That reference rounds only at the end. A program can round after every intermediate operation. We also measure forward error, the difference between the value returned by the computation and the exact value of the function, either as an absolute difference or relative to the exact answer when it is nonzero. We use the same measurements for gradients. For more background, Higham's book is a good reference.
\[ \begin{aligned} \text{absolute error}&=|\widehat{y}-y|,\\[3pt] \text{relative error}&=\frac{|\widehat{y}-y|}{|y|}. \end{aligned} \]
Let's check the error in Lean. FloatLib's roundoff tactic analyzes a floating-point expression against its real-valued reference. It follows the arithmetic operations, applies their rounding theorems, and combines the contributions into an absolute or mixed error bound. The command roundoff mixed theorem ... using ... generates a reusable theorem and the finiteness and range conditions needed for its proof. Once the remaining goals are discharged, Lean's kernel checks the theorem.2
When we ran roundoff on our old softmax implementation, it flagged the problem in under a second. For logits [9, -9, -9], with class 0 as the target, the original float32 computation gives a target gradient of zero, while the real gradient is about \(-3.046\times10^{-8}\). We can run this float32 calculation in Lean and check its error against the exact gradient.
Download the complete Lean example (Lean 4.35.0).
Definitions and real-gradient proof
import FloatLib.Numerics.Enclosure.Elementary.Proof
import TorchLean.NN.Softmax.Correctness
import TorchLean.Verify.RuntimeApprox.Roundoff.CrossEntropy
import TorchLeanExamples.DeepDives.Floats.RoundingBugs
/-!
## Definitions and the exact real-valued gradient
Checked with Lean 4.35.0 and TorchLean revision bb95db148ab63e3beb3e9c43813ad782bdddad67.
Run `lake env lean /path/to/SoftmaxBlog.lean` from that TorchLean checkout.
-/
namespace TorchLean.Examples.BlogSoftmax
open Tensor
open FloatLib.Floats FloatLib.Numerics
open FloatLib.Floats.Formats.BinaryInterchange
section Formulas
variable {α : Type} [Storage α] [Context α]
/-- Logits `[m, -m, -m]`. The target class `0` leads the other two by `2 * m`. -/
def logits (m : α) : Tensor α [3] := Tensor.ofFn fun i => if i = 0 then m else -m
/-- The target entry of the standard log-softmax at `logits m`. -/
def standardLogProbability (m : α) : α :=
(StandardSoftmax.logSoftmax 0 (logits m)).getScalar 0
/-- The standard cross-entropy of `logits m` against the target `0`. -/
def standardLoss (m : α) : α :=
StandardSoftmax.crossEntropyLogits 0 (logits m) SoftmaxCrossEntropy.target
/-- The target entry of the standard cross-entropy gradient at `logits m`. -/
def standardGradient (m : α) : α :=
(StandardSoftmax.crossEntropyLogitsDeriv 0 (logits m)
SoftmaxCrossEntropy.target).getScalar 0
/-- The target entry of `Tensor.crossEntropyBackward .logits` at `logits m`. -/
def gradient (m : α) : α :=
(Tensor.crossEntropyBackward .logits (logits m) SoftmaxCrossEntropy.target ⟨0,
by exact Nat.zero_lt_succ _⟩).getScalar 0
end Formulas
/-- The softmax probability `2 exp (-gap) / (1 + 2 exp (-gap))` of the two classes of
`logits (gap / 2)` other than the target. -/
noncomputable def tailMass (gap : ℝ) : ℝ :=
2 * Real.exp (-gap) / (1 + 2 * Real.exp (-gap))
/-- Over the reals, the target gradient at `logits m` is `-tailMass (2 * m)`. -/
theorem gradient_real (m : ℝ) : gradient m = -tailMass (2 * m) := by
have connected := congrArg (fun value : Vec 3 => value 0)
(Tensor.getScalarE_logSoftmaxBackward (logits m)
(Tensor.map (fun x => -x) SoftmaxCrossEntropy.target))
have coordinate : gradient m = -1 + Real.exp m / (Real.exp m + 2 * Real.exp (-m)) := by
have hdenom : axisMeanDenom [3] ⟨0, Shape.AxisInBounds.proof⟩ = 1 := rfl
simp only [gradient, Tensor.crossEntropyBackward, CrossEntropy.logProbs_real, reduceIte, hdenom]
simp [Vec.logSoftmaxVJP, Vec.softmax, Vec.sumExp,
Fin.sum_univ_three, logits, SoftmaxCrossEntropy.target] at connected ⊢
rw [connected]
ring
have hexp : Real.exp (-(2 * m)) = Real.exp (-m) * Real.exp (-m) := by
rw [← Real.exp_add]
ring_nf
have hinverse : Real.exp m * Real.exp (-m) = 1 := by
rw [← Real.exp_add, add_neg_cancel, Real.exp_zero]
rw [coordinate, tailMass, hexp]
have hpositive : 0 < Real.exp (-m) := Real.exp_pos _
field_simp
nlinarith [hinverse]
end TorchLean.Examples.BlogSoftmax
An absolute error tolerance of \(10^{-7}\) would accept zero even though the target gradient has disappeared. So we check a mixed bound with relative allowance \(r\) and absolute allowance \(a\):
\[ |\widehat{y}-y|\le r|y|+a. \]
To exclude an incorrect zero, the allowed error must be smaller than the true gradient. Let \(u\) be unit roundoff and \(\eta\) the underflow allowance. At this input, we use:
\[ \begin{aligned} r&=32u,\qquad a=32\eta,\\ r|y|+a&\approx5.8\times10^{-14}. \end{aligned} \]
That bound rejects zero and accepts the replacement, whose measured error is about \(4.5\times10^{-16}\). The corresponding kernel checked statements are in RoundingBugs.lean.
Float32 counterexample and error bounds
/-! ## The binary32 counterexample and the replacement's error bound -/
namespace TorchLean.Examples.BlogSoftmax
open Tensor
open FloatLib.Floats FloatLib.Numerics
open FloatLib.Floats.Formats.BinaryInterchange
/-- Rational bounds `lo` and `hi` on the endpoints of FloatLib's enclosure of `exp (-gap)` bound
`tailMass gap` by `2 lo / (1 + 2 lo)` and `2 hi / (1 + 2 hi)`, so by any `a` below the
first and any `b` above the second. -/
private theorem tailMass_mem_Icc (gap degree : ℕ) (lo hi : ℚ) {a b : ℝ}
(hlo₀ : 0 ≤ lo) (hlo : lo ≤ (Enclosure.exp (-gap) degree).lo)
(hhi : (Enclosure.exp (-gap) degree).hi ≤ hi)
(ha : a ≤ ((2 * lo / (1 + 2 * lo) : ℚ) : ℝ)) (hb : ((2 * hi / (1 + 2 * hi) : ℚ) : ℝ) ≤ b) :
tailMass gap ∈ Set.Icc a b := by
obtain ⟨lower, upper⟩ := Enclosure.contains_exp (-gap) degree
have increasing {s t : ℝ} (hs : 0 ≤ s) (hst : s ≤ t) :
2 * s / (1 + 2 * s) ≤ 2 * t / (1 + 2 * t) := by
rw [div_le_div_iff₀ (by positivity) (by linarith)]
nlinarith
push_cast at lower upper ha hb ⊢
exact ⟨ha.trans (increasing (by exact_mod_cast hlo₀) ((Rat.cast_le.mpr hlo).trans lower)),
(increasing (Real.exp_pos _).le (upper.trans (Rat.cast_le.mpr hhi))).trans hb⟩
section Bounds
variable {format : FloatFormat} {plan : Configured.StoragePlan format} {code : Type}
[ExecFloat.ModelCodec plan (Model format) code]
local notation "Value" =>
ExecFloat.Binary format.expWidth format.fracWidth format.encoding format.exponentBias
format.expWidth_ge_two format.fracWidth_pos format.exponentBias_pos
format.exponentBias_le_maxFinite plan code
/-- A value that decodes to zero is not within 32 units of roundoff and underflow of `-c`, for
`c ∈ [lo, hi]` with `0 < lo`, when `32 (u hi + 2 ^ e)` is below `lo` for a power `2 ^ e` at least
the underflow allowance. -/
private theorem not_mixedError_of_eq_zero {x : Value} {c lo hi : ℝ} (e : ℤ)
(hx : ExecFloat.Binary.toRat? x = some 0) (hc : c ∈ Set.Icc lo hi) (hlo₀ : 0 < lo)
(he : FloatFormat.minSubnormalExponent format - 1 ≤ e)
(hallowance : 32 * (Model.unitRoundoffAt format * hi + 2 ^ e) < lo) :
¬ MixedError (ExecFloat.Binary.toReal x) (-c) (32 * Model.unitRoundoffAt format)
(32 * Model.underflowErrorAt format) := by
rw [ExecFloat.Binary.toReal_of_toRat?_eq_some hx, Rat.cast_zero]
intro bound
obtain ⟨hlo, hhi⟩ := hc
have hu := Model.unitRoundoffAt_pos format
have hη := Model.underflowErrorAt_le_zpow format he
have hscaled := mul_le_mul_of_nonneg_left hhi hu.le
have hpositive : 0 < c := hlo₀.trans_le hlo
have h := bound.bound
rw [zero_sub, neg_neg, abs_neg, abs_of_pos hpositive] at h
linarith
/-- A value that decodes to a negative `q` is finite, negative and within 32 units of roundoff
and underflow of `-c`, for `c ∈ [lo, hi]`, when `-32 u lo ≤ q + lo` and `q + hi ≤ 32 u lo`. -/
private theorem mixedError_of_eq_some {x : Value} {q : ℚ} {c lo hi : ℝ}
(hx : ExecFloat.Binary.toRat? x = some q) (hq : q < 0) (hc : c ∈ Set.Icc lo hi)
(hlower : -(32 * Model.unitRoundoffAt format * lo) ≤ q + lo)
(hupper : q + hi ≤ 32 * Model.unitRoundoffAt format * lo) :
ExecFloat.Binary.isFinite x = true ∧
MixedError (ExecFloat.Binary.toReal x) (-c) (32 * Model.unitRoundoffAt format)
(32 * Model.underflowErrorAt format) ∧
ExecFloat.Binary.toReal x < 0 := by
obtain ⟨hlo, hhi⟩ := hc
have hu := Model.unitRoundoffAt_pos format
have hscaled : 32 * Model.unitRoundoffAt format * lo ≤ 32 * Model.unitRoundoffAt format * |-c| :=
mul_le_mul_of_nonneg_left (hlo.trans ((le_abs_self c).trans (abs_neg c).ge)) (by positivity)
rw [ExecFloat.Binary.toReal_of_toRat?_eq_some hx]
refine ⟨Model.Algebraic.isFinite_of_toRat?_eq_some hx,
(MixedError.of_abs_sub_le_mul (by positivity) ?_).mono le_rfl
(mul_nonneg (by norm_num) (Model.underflowErrorAt_pos format).le),
by exact_mod_cast hq⟩
rw [sub_neg_eq_add, abs_le]
constructor <;> linarith
end Bounds
/-! ## Binary32
The paper's logits `[9, -9, -9]`. With a gap of `18`, `2 exp (-18)` is below the binary32 unit
roundoff `2^-24`. -/
/-- FloatLib's enclosure of `exp (-18)` gives `tailMass 18` to eight digits. -/
private theorem binary32_tailMass_mem_Icc :
tailMass 18 ∈ Set.Icc (30459958 / 10 ^ 15) (30459959 / 10 ^ 15) :=
tailMass_mem_Icc 18 30 (152299797 / 10 ^ 16) (152299798 / 10 ^ 16)
(by norm_num) (by decide +kernel) (by decide +kernel) (by norm_num) (by norm_num)
/-- The standard formulas evaluated with the binary32 primitives return zero for the target
log-probability, the loss and the target gradient. -/
theorem binary32_standard_toRat? :
ExecFloat.Binary.toRat? (standardLogProbability (9 : Binary32)) = some 0 ∧
ExecFloat.Binary.toRat? (standardLoss (9 : Binary32)) = some 0 ∧
ExecFloat.Binary.toRat? (standardGradient (9 : Binary32)) = some 0 := by
decide +kernel
/-- The exact probability of the non-target classes lies between `3e-8` and `3.1e-8`. -/
theorem binary32_tailMass_mem_Ioo :
tailMass 18 ∈ Set.Ioo (3 / 10 ^ 8) (31 / 10 ^ 9) := by
obtain ⟨lower, upper⟩ := binary32_tailMass_mem_Icc
exact ⟨lt_of_lt_of_le (by norm_num) lower, lt_of_le_of_lt upper (by norm_num)⟩
/-- An absolute tolerance of `1e-7` accepts the standard target gradient. -/
theorem binary32_abs_sub_lt :
|ExecFloat.Binary.toReal (standardGradient (9 : Binary32)) - -tailMass 18| <
1 / 10 ^ 7 := by
obtain ⟨lower, upper⟩ := binary32_tailMass_mem_Ioo
rw [ExecFloat.Binary.toReal_of_toRat?_eq_some binary32_standard_toRat?.2.2, Rat.cast_zero,
zero_sub, neg_neg, abs_of_pos (by linarith)]
linarith
/-- The mixed bound with 32 units of binary32 roundoff and underflow rejects the standard target
gradient. -/
theorem binary32_not_mixedError :
¬ MixedError (ExecFloat.Binary.toReal (standardGradient (9 : Binary32))) (-tailMass 18)
(32 * Model.unitRoundoffAt FloatFormat.binary32)
(32 * Model.underflowErrorAt FloatFormat.binary32) :=
not_mixedError_of_eq_zero (-64) binary32_standard_toRat?.2.2
binary32_tailMass_mem_Icc (by norm_num) (by decide)
(by norm_num [Model.unitRoundoffAt_eq, FloatFormat.binary32])
/-- The target gradient `gradient 9` is finite, negative and within the mixed bound with 32
units of binary32 roundoff and underflow. -/
theorem binary32_mixedError :
ExecFloat.Binary.isFinite (gradient (9 : Binary32)) = true ∧
MixedError (ExecFloat.Binary.toReal (gradient (9 : Binary32))) (-tailMass 18)
(32 * Model.unitRoundoffAt FloatFormat.binary32)
(32 * Model.underflowErrorAt FloatFormat.binary32) ∧
ExecFloat.Binary.toReal (gradient (9 : Binary32)) < 0 :=
mixedError_of_eq_some (q := -2143429 / 2 ^ 46) (by decide +kernel) (by norm_num)
binary32_tailMass_mem_Icc (by norm_num [Model.unitRoundoffAt_eq, FloatFormat.binary32])
(by norm_num [Model.unitRoundoffAt_eq, FloatFormat.binary32])
end TorchLean.Examples.BlogSoftmax
FloatLib can also carry these bounds through expressions with variables, loops, and tensor sums. For the replacement, the generated bound at our input is about \(4.6\times10^{-14}\). We separately proved a sign theorem: when the target logit is maximal and at least one other class has a positive exponential contribution, the rewritten target gradient remains negative, for any class count and IEEE format under the stated assumptions.
Reference proof and roundoff theorem
/-! ## Generating an error bound for variable inputs -/
namespace TorchLean.Examples.BlogSoftmaxRoundoff
open Tensor
open FloatLib.Floats FloatLib.Numerics
open FloatLib.Floats.Formats.BinaryInterchange
variable {format : FloatFormat} {plan : Configured.StoragePlan format} {code : Type}
[ExecFloat.ModelCodec plan (Model format) code]
local notation "Value" => ExecFloat (Configured.Family format code plan)
attribute [local roundoff_rule] TorchLean.Roundoff.CrossEntropy.log_probs_error
/-- The cross-entropy gradient's schedule on decoded logits `x`, with backward pivot `p'` and the
sum `S` of the exponentials `exp (x j)` folded in coordinate order, has the exact gradient
`softmax x i - [i = label]` as its reference: `exp (x j - log S)` is `softmax x j`, and at the
backward pivot the VJP's formula for the pivot entry has the same value. -/
theorem softmax_sub_oneHot_eq {n : Nat} (x : Fin (n + 1) → ℝ) (p' label i : Fin (n + 1)) :
let S := (Tensor.Rep.coordinates [n + 1]).foldl (fun sum coordinate =>
sum + Real.exp (x coordinate.1)) 0
let q (j : Fin (n + 1)) : ℝ := Real.exp (x j - Real.log S)
(if i = p' then
-(q p' - 1) * -(if i = label then 1 else 0) - q p' * if label = p' then 0 else -1
else q i - if i = label then 1 else 0) =
Real.exp (x i) / ∑ j, Real.exp (x j) - if i = label then 1 else 0 := by
intro S q
have hS : S = ∑ j, Real.exp (x j) := Tensor.Rep.foldl_coordinates_add fun j => Real.exp (x j)
have hq (j : Fin (n + 1)) : q j = Real.exp (x j) / ∑ k, Real.exp (x k) := by
change Real.exp (x j - Real.log S) = _
rw [Real.exp_sub, hS,
Real.exp_log (Finset.sum_pos (fun _ _ => Real.exp_pos _) Finset.univ_nonempty)]
simp only [hq]
split_ifs <;> simp_all
/-- `softmax_sub_oneHot_eq` on the decoded logits of a vector: the reference `roundoff` infers for
the cross-entropy gradient is the exact gradient. -/
theorem gradient_reference [Storage Value] {n : Nat} (t : Tensor Value [n + 1])
(label i : Fin (n + 1)) :
let p' : Fin (n + 1) := Softmax.pivot (CrossEntropy.vectorLogProbs t)
let x (j : Fin (n + 1)) : ℝ :=
ExecFloat.Binary.toReal (Tensor.Rep.get t (j, PUnit.unit))
let q (j : Fin (n + 1)) : ℝ := Real.exp (x j - Real.log
((Tensor.Rep.coordinates [n + 1]).foldl (fun sum coordinate =>
sum + Real.exp (x coordinate.1)) 0))
(if i = p' then
-(q p' - 1) * -(if i = label then 1 else 0) - q p' * if label = p' then 0 else -1
else q i - if i = label then 1 else 0) =
Real.exp (ExecFloat.Binary.toReal (t.getScalar i)) /
∑ j, Real.exp (ExecFloat.Binary.toReal (t.getScalar j)) -
if i = label then 1 else 0 := by
intro p' x q
simp only [Tensor.getScalar_eq_apply]
exact softmax_sub_oneHot_eq x p' label i
roundoff mixed theorem gradient_error using gradient_reference :=
fun [Storage Value] {n : Nat} (t : Tensor Value [n + 1]) (label : Fin (n + 1))
(_hformat : format.isIEEE = true)
(_hfinite : ∀ i, ExecFloat.Binary.isFinite (t.getScalar i) = true) (i : Fin (n + 1)) =>
ExecFloat.Binary.toReal ((Tensor.crossEntropyBackward .logits t
(Tensor.ofFn fun j => if j = label then 1 else 0)
⟨0, by exact Nat.zero_lt_succ _⟩).getScalar i)
end TorchLean.Examples.BlogSoftmaxRoundoff
Running the operators across precisions¶
Now let's look at what the operators actually returned across precisions and libraries. In the Lean sweep, 57,547 outputs (96.8%) agreed with the exact answer rounded once. Another 1,372 agreed with TorchLean's specified sequence of arithmetic steps, rather than a single final rounding. Intermediate rounding explains why those two references can give different answers. The figure puts Lean beside the seven numerical libraries and separates CPU from GPU wherever we have both. Each color records the largest error found among the tested inputs.
Arithmetic19 rows
addsubmuldivdiv floordiv truncfma (IEEE line)addcmuladdcdivlerpnegabssquarereciprocalscalefmodremaindercopysignnextafterRoots and powers6 rows
sqrtsqrt clampNegrsqrtcbrtpowhypotRounding to integers6 rows
floorceilroundtruncfracsignExponentials and logarithms7 rows
expexp2expm1loglog2log10log1pTrigonometric and hyperbolic13 rows
sincostanasinacosatanatan2sinhcoshtanhasinhacoshatanhActivations9 rows
reluleakyReLUelusigmoidsoftplussilugelu (tanh)gelu (erf)erfGuarded operations6 rows
safeLogsafeInvsafeDivsmoothAbsnanToNumclampComparisons and selection14 rows
maxminfmaxfmineqneltlegtgeisNaNisInfisFiniteselectReductions, scans and sorting15 rows
reduce sumreduce prodreduce maxreduce minmeancumsumcumprodcummaxcumminargmaxargminsortsort desctopktopKMaskSoftmax and losses14 rows
softmaxlogSoftmaxmaskedSoftmaxcrossEntropycrossEntropyProbsbinaryCrossEntropymseLossmaeLosshuberLosshingeLosspoissonLosslogCoshLosscosineLossdistillLayers13 rows
linearmatmulscaledMatmulcontractconvconvTransposepoolsmoothMaxPoollayerNormbatchNormbatchNormRunningembeddingdropoutAttention, scans and transforms6 rows
attentionattnFromScoresmultiheadAttnselectiveScanrfftirfftMovement and indexing17 rows
detachreshapepermutebroadcastfullLikeflipslicepadcatgatherscatterindexAtindicesencodeIndexdecodeIndexcastbitcastLogic, bits and integers14 rows
logicalNotlogicalAndlogicalOrlogicalXorbitwiseAndbitwiseOrbitwiseXorbitwiseNotbitwiseLeftShiftshiftRightArithshiftRightLogicalpopulationCountcountLeadZerosmulhiRandom3 rows
randUniformrandnbernoulliMaskNo rule1 row
customArithmetic and reference values
Library references use MPFR; Lean references use exact rationals and high-precision mpmath. Each reference is rounded once to the destination format. The red outline marks an IEEE operation in an IEEE format for which correct rounding is required. Missing counterparts and unsupported dtypes are not counted as successful tests.
Table: every cell as text
✓ correctly rounded at every input; a number is the worst error in ulps; ±0 only the sign of a zero differs; NaN/∞ a NaN or infinity where the exact value is finite (or the reverse); rejects: the library refuses the dtype; · not run or no counterpart.
| family | operator | format | Lean | PyTorch CPU | PyTorch GPU | JAX CPU | JAX GPU | TensorFlow CPU | TensorFlow GPU | NumPy CPU | CuPy GPU | ONNX Runtime CPU | ONNX Runtime GPU | MLX CPU |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arithmetic | add | float64 | ✓ | ✓ | ✓ | 9,007,199,254,740,990 | ✓ | 9,007,199,254,740,990 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | add | float32 | ✓ | ✓ | ✓ | 16,777,214 | ✓ | 16,777,214 | 16,777,214 | ✓ | 16,777,214 | ✓ | ✓ | ✓ |
| Arithmetic | add | bfloat16 | ✓ | ✓ | ✓ | 254 | ✓ | 254 | 254 | ✓ | 254 | rejects | ✓ | ✓ |
| Arithmetic | add | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | add | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | add | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | add | TF32 | ✓ | |||||||||||
| Arithmetic | add | posit16 | ✓ | |||||||||||
| Arithmetic | sub | float64 | ✓ | ✓ | ✓ | 4,503,599,627,370,495 | ✓ | 4,503,599,627,370,495 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | sub | float32 | ✓ | ✓ | ✓ | 8,582,326 | ✓ | 8,582,326 | 8,582,326 | ✓ | 8,582,326 | ✓ | ✓ | ✓ |
| Arithmetic | sub | bfloat16 | ✓ | ✓ | ✓ | 176 | ✓ | 176 | 176 | ✓ | 176 | rejects | ✓ | ✓ |
| Arithmetic | sub | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | sub | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | sub | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | sub | TF32 | ✓ | |||||||||||
| Arithmetic | sub | posit16 | ✓ | |||||||||||
| Arithmetic | mul | float64 | ✓ | ✓ | ✓ | 4,598,966,579,610,778,593 | ✓ | 4,598,966,579,610,778,593 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | mul | float32 | ✓ | ✓ | ✓ | 1,082,130,429 | ✓ | 1,082,130,429 | 1,082,130,429 | ✓ | 1,082,130,429 | ✓ | ✓ | ✓ |
| Arithmetic | mul | bfloat16 | ✓ | ✓ | ✓ | 16,509 | ✓ | 16,509 | 16,509 | ✓ | 16,509 | rejects | ✓ | ✓ |
| Arithmetic | mul | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | mul | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | mul | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | mul | TF32 | ✓ | |||||||||||
| Arithmetic | mul | posit16 | ✓ | |||||||||||
| Arithmetic | div | float64 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | div | float32 | ✓ | ✓ | ✓ | NaN/∞ | 2 | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | ✓ |
| Arithmetic | div | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | ✓ | ✓ |
| Arithmetic | div | float16 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | div | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | div | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | div | TF32 | ✓ | |||||||||||
| Arithmetic | div | posit16 | ✓ | |||||||||||
| Arithmetic | div floor | float64 | ✓ | 2 | 2 | NaN/∞ | 2 | NaN/∞ | 4,607,182,418,800,017,408 | 2 | 4,607,182,418,800,017,408 | 4,607,182,418,800,017,408 | 4,607,182,418,800,017,408 | 4,607,182,418,800,017,408 |
| Arithmetic | div floor | float32 | ≤1 | 2 | 2 | NaN/∞ | 4 | NaN/∞ | NaN/∞ | 2 | NaN/∞ | 1,065,353,216 | 1,065,353,216 | 1,065,353,216 |
| Arithmetic | div floor | bfloat16 | ✓ | 2 | conv | NaN/∞ | 2 | NaN/∞ | NaN/∞ | conv | NaN/∞ | rejects | rejects | 16,256 |
| Arithmetic | div floor | float16 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | 15,360 | 15,360 | NaN/∞ | 15,360 | 15,360 | 15,360 | 15,360 |
| Arithmetic | div floor | float8 E5M2 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Arithmetic | div floor | float8 E4M3 | ≤1 | conv | conv | 2 | 2 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | div floor | TF32 | ≤1 | |||||||||||
| Arithmetic | div trunc | float64 | ✓ | 2,251,799,813,685,248 | 2,251,799,813,685,248 | NaN/∞ | 2,251,799,813,685,248 | NaN/∞ | 2,251,799,813,685,248 | · | 2,251,799,813,685,248 | 2,251,799,813,685,248 | 2,251,799,813,685,248 | rejects |
| Arithmetic | div trunc | float32 | ≤1 | 4,194,304 | 4,194,304 | NaN/∞ | 1,065,353,216 | NaN/∞ | NaN/∞ | · | NaN/∞ | 4,194,304 | 4,194,304 | rejects |
| Arithmetic | div trunc | bfloat16 | ✓ | 64 | 64 | NaN/∞ | 16,256 | NaN/∞ | NaN/∞ | · | NaN/∞ | rejects | rejects | rejects |
| Arithmetic | div trunc | float16 | ≤1 | 512 | 512 | 512 | 512 | 512 | 512 | · | 512 | ±0 | 512 | rejects |
| Arithmetic | div trunc | float8 E5M2 | 2 | ✓ | ✓ | 2 | 60 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Arithmetic | div trunc | float8 E4M3 | ≤1 | conv | conv | 4 | 56 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Arithmetic | div trunc | TF32 | ≤1 | |||||||||||
| Arithmetic | fma (IEEE line) | float64 | · | ✓ | ✓ | 4,798,521,906,915,898,289 | 1,989,962,520,682 | · | · | · | ✓ | rejects | rejects | rejects |
| Arithmetic | fma (IEEE line) | float32 | · | ✓ | ✓ | 1,743,574,162 | 919,753,968 | · | · | · | 1,743,574,162 | rejects | rejects | rejects |
| Arithmetic | fma (IEEE line) | bfloat16 | · | ≤1 | ≤1 | 30,907 | ≤1 | · | · | · | rejects | rejects | rejects | rejects |
| Arithmetic | fma (IEEE line) | float16 | · | ≤1 | ≤1 | NaN/∞ | NaN/∞ | · | · | · | rejects | rejects | rejects | rejects |
| Arithmetic | fma (IEEE line) | float8 E5M2 | · | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | · | · | · | rejects | rejects | rejects | rejects |
| Arithmetic | fma (IEEE line) | float8 E4M3 | · | conv | conv | NaN/∞ | ≤1 | · | · | · | rejects | rejects | rejects | rejects |
| Arithmetic | addcmul | float64 | ≤1 | ✓ | ✓ | 4,865,530,273,319,972,487 | 2,648,791,123,070 | 4,865,530,273,319,972,487 | 2,648,791,123,070 | 2,648,791,123,070 | 2,648,791,123,070 | 2,648,791,123,070 | 2,648,791,123,070 | 2,648,791,123,070 |
| Arithmetic | addcmul | float32 | ≤1 | ✓ | ✓ | 2,055,270,886 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Arithmetic | addcmul | bfloat16 | ≤1 | ≤1 | ≤1 | 29,559 | ≤1 | 29,559 | 29,559 | 23,840 | 29,559 | rejects | 23,840 | 23,840 |
| Arithmetic | addcmul | float16 | NaN/∞ | ≤1 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ |
| Arithmetic | addcmul | float8 E5M2 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | rejects | ≤1 | ≤1 | rejects |
| Arithmetic | addcmul | float8 E4M3 | ≤1 | conv | conv | NaN/∞ | ≤1 | ✓ | ✓ | NaN/∞ | rejects | conv | conv | rejects |
| Arithmetic | addcmul | TF32 | ≤1 | |||||||||||
| Arithmetic | addcdiv | float64 | 3 | 3,547,485,734,686 | 3,547,485,734,686 | NaN/∞ | 3,547,485,734,686 | NaN/∞ | 3,547,485,734,686 | 3,547,485,734,686 | 3,547,485,734,686 | 3,547,485,734,686 | 3,547,485,734,686 | 3,547,485,734,686 |
| Arithmetic | addcdiv | float32 | ≤1 | 970,800,625 | 970,800,625 | NaN/∞ | 970,800,625 | NaN/∞ | NaN/∞ | 970,800,625 | NaN/∞ | 970,800,625 | 970,800,625 | 970,800,625 |
| Arithmetic | addcdiv | bfloat16 | ≤1 | ≤1 | ≤1 | NaN/∞ | 14,720 | NaN/∞ | NaN/∞ | 26,186 | NaN/∞ | rejects | 26,186 | 26,186 |
| Arithmetic | addcdiv | float16 | NaN/∞ | 8 | 8 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | 8 | NaN/∞ | NaN/∞ |
| Arithmetic | addcdiv | float8 E5M2 | ≤1 | conv | conv | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | rejects | ≤1 | ≤1 | rejects |
| Arithmetic | addcdiv | float8 E4M3 | ≤1 | conv | conv | NaN/∞ | ≤1 | ✓ | ✓ | NaN/∞ | rejects | conv | conv | rejects |
| Arithmetic | addcdiv | TF32 | ≤1 | |||||||||||
| Arithmetic | lerp | float64 | 3 | 2,048 | 2,048 | 4,682,947,832,717,916,909 | 2,599 | 4,682,947,832,717,916,909 | 17,698 | 17,698 | 2,599 | 2,599 | 2,599 | 2,599 |
| Arithmetic | lerp | float32 | 3 | 4,278,190,079 | 4,278,190,079 | 1,673,840,181 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Arithmetic | lerp | bfloat16 | 3 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | 3 | rejects | 3 | NaN/∞ |
| Arithmetic | lerp | float16 | NaN/∞ | ≤1 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ |
| Arithmetic | lerp | float8 E5M2 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | rejects | ≤1 | ≤1 | rejects |
| Arithmetic | lerp | float8 E4M3 | 3 | conv | conv | NaN/∞ | 3 | ✓ | ✓ | NaN/∞ | rejects | ✓ | ✓ | rejects |
| Arithmetic | lerp | TF32 | 3 | |||||||||||
| Arithmetic | neg | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | neg | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 8,388,607 | ✓ | 8,388,607 | ✓ | ✓ | ✓ |
| Arithmetic | neg | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | rejects | ✓ | ✓ |
| Arithmetic | neg | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | neg | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | neg | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | neg | TF32 | ✓ | |||||||||||
| Arithmetic | neg | posit16 | ✓ | |||||||||||
| Arithmetic | abs | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | abs | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 8,388,607 | ✓ | 8,388,607 | ✓ | ✓ | ✓ |
| Arithmetic | abs | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | rejects | ✓ | ✓ |
| Arithmetic | abs | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | abs | float8 E5M2 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | abs | float8 E4M3 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | abs | TF32 | ✓ | |||||||||||
| Arithmetic | abs | posit16 | ✓ | |||||||||||
| Arithmetic | square | float64 | ✓ | ✓ | ✓ | 4,502,387,152,236,452 | ✓ | 4,502,387,152,236,452 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | square | float32 | ✓ | ✓ | ✓ | 8,271,479 | ✓ | 8,271,479 | 8,271,479 | ✓ | 8,271,479 | ✓ | ✓ | ✓ |
| Arithmetic | square | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | 127 | 127 | ✓ | 127 | rejects | ✓ | ✓ |
| Arithmetic | square | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | square | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | square | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | square | TF32 | ✓ | |||||||||||
| Arithmetic | square | posit16 | ✓ | |||||||||||
| Arithmetic | reciprocal | float64 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | reciprocal | float32 | ✓ | ✓ | ✓ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | ✓ |
| Arithmetic | reciprocal | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | rejects | ✓ |
| Arithmetic | reciprocal | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | reciprocal | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | reciprocal | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | reciprocal | TF32 | ✓ | |||||||||||
| Arithmetic | reciprocal | posit16 | ✓ | |||||||||||
| Arithmetic | scale | float64 | ✓ | ✓ | ✓ | 4,469,646,987,026,863 | ✓ | 4,469,646,987,026,863 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | scale | float32 | ✓ | ✓ | ✓ | 8,366,804 | ✓ | 8,366,804 | 8,366,804 | ✓ | 8,366,804 | ✓ | ✓ | ✓ |
| Arithmetic | scale | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | 127 | 127 | ✓ | 127 | rejects | ✓ | ✓ |
| Arithmetic | scale | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Arithmetic | scale | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ≤1 | ≤1 | rejects |
| Arithmetic | scale | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | conv | conv | rejects |
| Arithmetic | scale | TF32 | ✓ | |||||||||||
| Arithmetic | scale | posit16 | ✓ | |||||||||||
| Arithmetic | fmod | float64 | ✓ | NaN/∞ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | rejects |
| Arithmetic | fmod | float32 | ✓ | NaN/∞ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | rejects |
| Arithmetic | fmod | bfloat16 | ✓ | NaN/∞ | ✓ | NaN/∞ | ✓ | rejects | rejects | ✓ | NaN/∞ | rejects | ✓ | rejects |
| Arithmetic | fmod | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | ✓ | ✓ | ✓ | rejects |
| Arithmetic | fmod | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | fmod | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | fmod | TF32 | ✓ | |||||||||||
| Arithmetic | remainder | float64 | ±0 | NaN/∞ | ±0 | NaN/∞ | ±0 | NaN/∞ | ±0 | ✓ | NaN/∞ | rejects | rejects | ±0 |
| Arithmetic | remainder | float32 | ±0 | NaN/∞ | ±0 | NaN/∞ | ±0 | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | rejects | ±0 |
| Arithmetic | remainder | bfloat16 | ±0 | NaN/∞ | ±0 | NaN/∞ | ±0 | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | rejects | 65,279 |
| Arithmetic | remainder | float16 | ±0 | ±0 | ±0 | ±0 | ±0 | ±0 | ±0 | ✓ | NaN/∞ | rejects | rejects | NaN/∞ |
| Arithmetic | remainder | float8 E5M2 | ±0 | ±0 | ±0 | ±0 | ±0 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | remainder | float8 E4M3 | ±0 | ±0 | ±0 | ±0 | ±0 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | remainder | TF32 | ±0 | |||||||||||
| Arithmetic | copysign | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ | ✓ | rejects | rejects | rejects |
| Arithmetic | copysign | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ | ✓ | rejects | rejects | rejects |
| Arithmetic | copysign | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ | ✓ | rejects | rejects | rejects |
| Arithmetic | copysign | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ | ✓ | rejects | rejects | rejects |
| Arithmetic | copysign | float8 E5M2 | ✓ | ✓ | ✓ | rejects | rejects | · | · | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | copysign | float8 E4M3 | ✓ | ✓ | ✓ | rejects | rejects | · | · | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | copysign | TF32 | ✓ | |||||||||||
| Arithmetic | nextafter | float64 | ✓ | ✓ | ✓ | 8,279,395,750,864,635 | ✓ | 8,279,395,750,864,635 | ✓ | ✓ | ✓ | rejects | rejects | rejects |
| Arithmetic | nextafter | float32 | ✓ | ✓ | ✓ | 16,758,093 | ✓ | 16,758,093 | 16,758,093 | ✓ | 16,777,214 | rejects | rejects | rejects |
| Arithmetic | nextafter | bfloat16 | ✓ | ✓ | ✓ | 253 | ✓ | rejects | rejects | ✓ | 127 | rejects | rejects | rejects |
| Arithmetic | nextafter | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | NaN/∞ | rejects | rejects | rejects |
| Arithmetic | nextafter | float8 E5M2 | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | nextafter | float8 E4M3 | ✓ | ≤1 | ≤1 | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Arithmetic | nextafter | TF32 | ✓ | |||||||||||
| Roots and powers | sqrt | float64 | ✓ | ≤1 | ✓ | 2,305,843,009,213,693,951 | ✓ | 2,305,843,009,213,693,951 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Roots and powers | sqrt | float32 | ✓ | ≤1 | ✓ | 536,870,911 | ≤1 | 536,870,911 | 536,870,911 | ✓ | 536,870,911 | ✓ | ✓ | ✓ |
| Roots and powers | sqrt | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | ✓ | ✓ |
| Roots and powers | sqrt | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Roots and powers | sqrt | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | sqrt | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | sqrt | TF32 | ✓ | |||||||||||
| Roots and powers | sqrt | posit16 | ✓ | |||||||||||
| Roots and powers | sqrt clampNeg | float64 | ✓ | ≤1 | ✓ | 2,305,843,009,213,693,951 | ✓ | 2,305,843,009,213,693,951 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Roots and powers | sqrt clampNeg | float32 | ✓ | ≤1 | ✓ | 536,870,911 | ≤1 | 536,870,911 | 536,870,911 | ✓ | 536,870,911 | ✓ | ✓ | ✓ |
| Roots and powers | sqrt clampNeg | bfloat16 | ✓ | ±0 | ✓ | 8,191 | ✓ | 8,191 | 8,191 | ✓ | 8,191 | rejects | ✓ | ✓ |
| Roots and powers | sqrt clampNeg | float16 | ✓ | ±0 | ✓ | ✓ | ✓ | ±0 | ✓ | ±0 | ✓ | ±0 | ✓ | ✓ |
| Roots and powers | sqrt clampNeg | float8 E5M2 | ±0 | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | sqrt clampNeg | float8 E4M3 | ±0 | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | sqrt clampNeg | TF32 | ✓ | |||||||||||
| Roots and powers | rsqrt | float64 | ≤1 | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Roots and powers | rsqrt | float32 | ≤1 | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | ≤1 | ≤1 | ≤1 |
| Roots and powers | rsqrt | bfloat16 | ≤1 | ≤1 | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ≤1 | rejects | rejects | rejects | ≤1 |
| Roots and powers | rsqrt | float16 | ≤1 | ≤1 | ✓ | ✓ | ✓ | ≤1 | ✓ | ≤1 | ✓ | ✓ | ≤1 | ≤1 |
| Roots and powers | rsqrt | float8 E5M2 | ≤1 | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ≤1 | rejects | rejects | rejects | rejects |
| Roots and powers | rsqrt | float8 E4M3 | ≤1 | conv | conv | ✓ | ✓ | rejects | rejects | ≤1 | rejects | rejects | rejects | rejects |
| Roots and powers | rsqrt | TF32 | ≤1 | |||||||||||
| Roots and powers | rsqrt | posit16 | ✓ | |||||||||||
| Roots and powers | cbrt | float64 | ✓ | · | · | 3,072,625,526,210,130,570 | ✓ | 3,072,625,526,210,130,570 | 119 | ≤1 | ✓ | rejects | rejects | rejects |
| Roots and powers | cbrt | float32 | ✓ | · | · | 1,352,746,263 | ≤1 | 713,031,679 | 713,031,679 | 2 | 713,031,679 | rejects | rejects | rejects |
| Roots and powers | cbrt | bfloat16 | ✓ | · | · | 20,640 | ✓ | rejects | rejects | ✓ | 10,879 | rejects | rejects | rejects |
| Roots and powers | cbrt | float16 | ✓ | · | · | ≤1 | ≤1 | 3 | 3 | ✓ | ≤1 | rejects | rejects | rejects |
| Roots and powers | cbrt | float8 E5M2 | ✓ | · | · | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | cbrt | float8 E4M3 | ✓ | · | · | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | cbrt | TF32 | ✓ | |||||||||||
| Roots and powers | cbrt | posit16 | ✓ | |||||||||||
| Roots and powers | pow | float64 | ✓ | ≤1 | ≤1 | 201,622,187,196,946,263 | ≤1 | NaN/∞ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Roots and powers | pow | float32 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | ≤1 | ≤1 | ≤1 |
| Roots and powers | pow | bfloat16 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | rejects | ≤1 | ≤1 |
| Roots and powers | pow | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Roots and powers | pow | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | pow | float8 E4M3 | ✓ | conv | conv | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | pow | TF32 | ✓ | |||||||||||
| Roots and powers | hypot | float64 | ✓ | ≤1 | 2 | 6,369,051,672,525,771 | ≤1 | NaN/∞ | NaN/∞ | ≤1 | 2 | rejects | rejects | rejects |
| Roots and powers | hypot | float32 | ✓ | ≤1 | ≤1 | 11,863,282 | ≤1 | NaN/∞ | NaN/∞ | ✓ | 11,863,282 | rejects | rejects | rejects |
| Roots and powers | hypot | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | rejects | rejects | ✓ | 180 | rejects | rejects | rejects |
| Roots and powers | hypot | float16 | ✓ | ≤1 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | ≤1 | rejects | rejects | rejects |
| Roots and powers | hypot | float8 E5M2 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | hypot | float8 E4M3 | ✓ | conv | conv | NaN/∞ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Roots and powers | hypot | TF32 | ✓ | |||||||||||
| Roots and powers | hypot | posit16 | ✓ | |||||||||||
| Rounding to integers | floor | float64 | ✓ | ✓ | ✓ | 4,607,182,418,800,017,408 | ✓ | 4,607,182,418,800,017,408 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | floor | float32 | ✓ | ✓ | ✓ | 1,065,353,216 | ✓ | 1,065,353,216 | 1,065,353,216 | ✓ | 1,065,353,216 | ✓ | ✓ | ✓ |
| Rounding to integers | floor | bfloat16 | ✓ | ✓ | ✓ | 16,256 | ✓ | 16,256 | 16,256 | ✓ | 16,256 | rejects | rejects | ✓ |
| Rounding to integers | floor | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | floor | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | floor | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | floor | TF32 | ✓ | |||||||||||
| Rounding to integers | floor | posit16 | ✓ | |||||||||||
| Rounding to integers | ceil | float64 | ✓ | ✓ | ✓ | 4,607,182,418,800,017,408 | ✓ | 4,607,182,418,800,017,408 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | ceil | float32 | ✓ | ✓ | ✓ | 1,065,353,216 | ✓ | 1,065,353,216 | 1,065,353,216 | ✓ | 1,065,353,216 | ✓ | ✓ | ✓ |
| Rounding to integers | ceil | bfloat16 | ✓ | ✓ | ✓ | 16,256 | ✓ | 16,256 | 16,256 | ✓ | 16,256 | rejects | rejects | ✓ |
| Rounding to integers | ceil | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | ceil | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | ceil | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | ceil | TF32 | ✓ | |||||||||||
| Rounding to integers | ceil | posit16 | ✓ | |||||||||||
| Rounding to integers | round | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | round | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | round | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Rounding to integers | round | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rounding to integers | round | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | round | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | round | TF32 | ✓ | |||||||||||
| Rounding to integers | round | posit16 | ✓ | |||||||||||
| Rounding to integers | trunc | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | rejects |
| Rounding to integers | trunc | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | rejects |
| Rounding to integers | trunc | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | ✓ | rejects | rejects | rejects |
| Rounding to integers | trunc | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ±0 | ✓ | rejects |
| Rounding to integers | trunc | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | trunc | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | trunc | TF32 | ✓ | |||||||||||
| Rounding to integers | frac | float64 | ✓ | ✓ | ✓ | 4,503,599,627,370,495 | ✓ | 4,503,599,627,370,495 | ✓ | conv | conv | ±0 | ±0 | rejects |
| Rounding to integers | frac | float32 | ✓ | ✓ | ✓ | 8,388,607 | ✓ | 8,388,607 | 8,388,607 | conv | 8,388,607 | ±0 | ±0 | rejects |
| Rounding to integers | frac | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | rejects | rejects | conv | 127 | rejects | ±0 | rejects |
| Rounding to integers | frac | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | ±0 | ±0 | rejects |
| Rounding to integers | frac | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Rounding to integers | frac | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ±0 | rejects | rejects | rejects | rejects |
| Rounding to integers | frac | TF32 | ✓ | |||||||||||
| Rounding to integers | sign | float64 | ✓ | conv | conv | 4,607,182,418,800,017,408 | ✓ | 4,611,685,723,220,863,488 | ✓ | ±0 | ±0 | ±0 | conv | conv |
| Rounding to integers | sign | float32 | ✓ | conv | conv | 1,065,353,216 | ✓ | 1,073,741,518 | 1,065,353,216 | ±0 | 1,065,353,216 | ±0 | conv | conv |
| Rounding to integers | sign | bfloat16 | ✓ | conv | conv | 16,256 | ✓ | 16,383 | 16,256 | ✓ | 16,256 | conv | conv | conv |
| Rounding to integers | sign | float16 | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | ±0 | ✓ | ±0 | ±0 | NaN/∞ | NaN/∞ | NaN/∞ |
| Rounding to integers | sign | float8 E5M2 | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | sign | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Rounding to integers | sign | TF32 | ✓ | |||||||||||
| Rounding to integers | sign | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | exp | float64 | ✓ | ≤1 | ≤1 | 4,492,676,999,583,826 | ≤1 | 4,492,676,999,583,826 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | NaN/∞ |
| Exponentials and logarithms | exp | float32 | ✓ | ≤1 | 2 | 8,386,470 | 2 | 8,386,470 | 8,386,470 | 2 | 8,386,470 | ≤1 | 2 | NaN/∞ |
| Exponentials and logarithms | exp | bfloat16 | ✓ | ✓ | ✓ | 109 | ≤1 | 109 | 109 | ✓ | 109 | rejects | ✓ | NaN/∞ |
| Exponentials and logarithms | exp | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Exponentials and logarithms | exp | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | exp | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | exp | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | exp | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | exp2 | float64 | ✓ | ≤1 | ≤1 | 4,501,466,744,494,178 | 723 | 4,501,466,744,494,178 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects |
| Exponentials and logarithms | exp2 | float32 | ✓ | ≤1 | 2 | 8,385,947 | 68 | 8,385,947 | 8,385,947 | 3 | 8,385,947 | ≤1 | ≤1 | rejects |
| Exponentials and logarithms | exp2 | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | rejects | rejects | ✓ | 91 | rejects | ✓ | rejects |
| Exponentials and logarithms | exp2 | float16 | ✓ | ≤1 | ≤1 | 14 | 14 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects |
| Exponentials and logarithms | exp2 | float8 E5M2 | ✓ | ✓ | ✓ | 7 | 4 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | exp2 | float8 E4M3 | ✓ | conv | conv | 2 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | exp2 | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | expm1 | float64 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | 3 | ≤1 | ≤1 | ≤1 | 4,368,491,279,861,963,939 | 4,368,491,279,861,963,939 | ≤1 |
| Exponentials and logarithms | expm1 | float32 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | 3 | 8,388,607 | 3 | 8,388,607 | 864,026,624 | 867,266,040 | ≤1 |
| Exponentials and logarithms | expm1 | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | ✓ | 127 | rejects | 15,231 | ✓ |
| Exponentials and logarithms | expm1 | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,095 | ≤1 |
| Exponentials and logarithms | expm1 | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | expm1 | float8 E4M3 | ≤1 | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | expm1 | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | expm1 | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | log | float64 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Exponentials and logarithms | log | float32 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | 3 | NaN/∞ | 3 | ≤1 | ≤1 |
| Exponentials and logarithms | log | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | rejects | rejects | ✓ |
| Exponentials and logarithms | log | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Exponentials and logarithms | log | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | log | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | log2 | float64 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | 2 | ≤1 | ≤1 | 2 | 2 | ≤1 |
| Exponentials and logarithms | log2 | float32 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ | 2 | NaN/∞ | 3 | ≤1 | ≤1 |
| Exponentials and logarithms | log2 | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | 2 | rejects | rejects | ✓ | NaN/∞ | rejects | rejects | ✓ |
| Exponentials and logarithms | log2 | float16 | ✓ | ✓ | ✓ | 2 | 2 | 2 | 2 | ✓ | ✓ | ≤1 | 2 | ✓ |
| Exponentials and logarithms | log2 | float8 E5M2 | ✓ | ✓ | ✓ | 2 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log2 | float8 E4M3 | ✓ | conv | conv | 2 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log2 | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | log2 | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | log10 | float64 | ✓ | ≤1 | ≤1 | NaN/∞ | 2 | NaN/∞ | 2 | ≤1 | ≤1 | 3 | 2 | 2 |
| Exponentials and logarithms | log10 | float32 | ✓ | ≤1 | 2 | NaN/∞ | 2 | NaN/∞ | NaN/∞ | 2 | NaN/∞ | 4 | 2 | 2 |
| Exponentials and logarithms | log10 | bfloat16 | ✓ | ✓ | ✓ | NaN/∞ | 2 | rejects | rejects | ✓ | NaN/∞ | rejects | rejects | ✓ |
| Exponentials and logarithms | log10 | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Exponentials and logarithms | log10 | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log10 | float8 E4M3 | ✓ | conv | conv | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log10 | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | log10 | posit16 | ✓ | |||||||||||
| Exponentials and logarithms | log1p | float64 | ✓ | ≤1 | ≤1 | 4,503,599,627,370,495 | ≤1 | 4,503,599,627,370,495 | ≤1 | ≤1 | ≤1 | 4,368,491,427,922,774,011 | 4,368,491,427,922,774,011 | ≤1 |
| Exponentials and logarithms | log1p | float32 | ✓ | ≤1 | ≤1 | 8,388,607 | ≤1 | 8,388,607 | 8,388,607 | 2 | 8,388,607 | 864,026,624 | 864,026,624 | ≤1 |
| Exponentials and logarithms | log1p | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | 127 | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Exponentials and logarithms | log1p | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,096 | ≤1 |
| Exponentials and logarithms | log1p | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log1p | float8 E4M3 | ≤1 | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Exponentials and logarithms | log1p | TF32 | ✓ | |||||||||||
| Exponentials and logarithms | log1p | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | sin | float64 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,368,955,796,522,032,135 | ≤1 | 9,195,615,027,676,118,220 |
| Trigonometric and hyperbolic | sin | float32 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | 8,388,607 | 8,388,607 | ≤1 | 8,388,607 | 2 | ≤1 | 1,081,763,405 |
| Trigonometric and hyperbolic | sin | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | 127 | ✓ | 127 | rejects | ✓ | NaN/∞ |
| Trigonometric and hyperbolic | sin | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 |
| Trigonometric and hyperbolic | sin | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | sin | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | sin | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | sin | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | cos | float64 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 650,613 | ≤1 | 9,195,398,567,459,499,637 |
| Trigonometric and hyperbolic | cos | float32 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | 2 | ≤1 | 2,432 |
| Trigonometric and hyperbolic | cos | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | NaN/∞ |
| Trigonometric and hyperbolic | cos | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 |
| Trigonometric and hyperbolic | cos | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | cos | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | cos | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | cos | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | tan | float64 | ✓ | ≤1 | 2 | ≤1 | 2 | ≤1 | 2 | ≤1 | 2 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | tan | float32 | ✓ | ≤1 | 3 | ≤1 | 3 | ≤1 | 8,388,607 | 3 | 8,388,607 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | tan | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | tan | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | tan | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | tan | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | tan | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | tan | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | asin | float64 | ✓ | ≤1 | 2 | 4,503,599,627,370,495 | 2 | ≤1 | 2 | ≤1 | 2 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | asin | float32 | ✓ | ≤1 | ≤1 | 2 | ≤1 | 8,388,607 | 8,388,608 | 3 | 8,388,607 | 4 | rejects | ≤1 |
| Trigonometric and hyperbolic | asin | bfloat16 | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | asin | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 | ≤1 | ✓ | rejects | ✓ |
| Trigonometric and hyperbolic | asin | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | asin | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | asin | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | asin | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | acos | float64 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | acos | float32 | ✓ | ≤1 | ≤1 | 2 | ≤1 | 4 | 2 | 2 | ≤1 | 4 | rejects | ≤1 |
| Trigonometric and hyperbolic | acos | bfloat16 | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | acos | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | acos | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | acos | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | acos | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | acos | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atan | float64 | ✓ | ≤1 | ≤1 | 4,437,541,851,369,665 | ≤1 | 4,503,599,627,370,495 | ≤1 | ≤1 | ≤1 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | atan | float32 | ✓ | ≤1 | ≤1 | 8,383,327 | ≤1 | 8,388,607 | 8,388,607 | 2 | 8,388,607 | 3 | rejects | ≤1 |
| Trigonometric and hyperbolic | atan | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | atan | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | atan | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atan | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atan | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atan | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atan2 | float64 | ✓ | ≤1 | 2 | 9,218,230,760,605,459,920 | 2 | 4,605,249,457,297,304,857 | 2 | ≤1 | 2 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | atan2 | float32 | ✓ | ≤1 | 2 | NaN/∞ | 2 | 1,061,752,794 | 1,070,141,403 | 2 | 1,070,141,403 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | atan2 | bfloat16 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | NaN/∞ | 16,329 | ≤1 | 16,329 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | atan2 | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | atan2 | float8 E5M2 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | rejects | rejects | ≤1 | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atan2 | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atan2 | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atan2 | posit16 | conv | |||||||||||
| Trigonometric and hyperbolic | sinh | float64 | ✓ | NaN/∞ | ≤1 | 4,503,599,627,370,495 | ≤1 | 2 | 496 | ≤1 | ≤1 | rejects | rejects | 2 |
| Trigonometric and hyperbolic | sinh | float32 | ✓ | NaN/∞ | 2 | 8,388,607 | 2 | 2 | 8,388,607 | ≤1 | 8,388,607 | 2 | rejects | 2 |
| Trigonometric and hyperbolic | sinh | bfloat16 | ✓ | NaN/∞ | ✓ | 127 | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | sinh | float16 | ✓ | ≤1 | ✓ | ≤1 | ✓ | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | sinh | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | sinh | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | sinh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | sinh | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | cosh | float64 | ✓ | NaN/∞ | ≤1 | 496 | ≤1 | 2 | 496 | ≤1 | ≤1 | rejects | rejects | 2 |
| Trigonometric and hyperbolic | cosh | float32 | ✓ | NaN/∞ | 2 | 24 | 2 | 2 | 25 | 2 | 2 | 2 | rejects | 2 |
| Trigonometric and hyperbolic | cosh | bfloat16 | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | cosh | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | cosh | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | cosh | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | cosh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | cosh | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | tanh | float64 | ✓ | ≤1 | ≤1 | 4,503,599,627,370,495 | ≤1 | 4,503,599,627,370,495 | ≤1 | ≤1 | ≤1 | 7 | ≤1 | 2 |
| Trigonometric and hyperbolic | tanh | float32 | ✓ | ≤1 | 2 | 4 | 5 | 8,388,607 | 5 | ≤1 | 8,388,607 | 103 | 2 | 2 |
| Trigonometric and hyperbolic | tanh | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | 127 | ✓ | 127 | rejects | ✓ | ✓ |
| Trigonometric and hyperbolic | tanh | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Trigonometric and hyperbolic | tanh | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | tanh | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | tanh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | tanh | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | asinh | float64 | ✓ | ≤1 | 2 | 4,503,599,627,370,495 | 2 | ≤1 | 2 | ≤1 | 2 | rejects | rejects | ≤1 |
| Trigonometric and hyperbolic | asinh | float32 | ✓ | 2 | 2 | 8,388,607 | 2 | 2 | 8,388,607 | ≤1 | 8,388,607 | 2 | rejects | 2 |
| Trigonometric and hyperbolic | asinh | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | asinh | float16 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | asinh | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | asinh | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | asinh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | asinh | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | acosh | float64 | ✓ | 2 | 2 | 3 | 2 | 2 | 3 | ≤1 | 2 | rejects | rejects | 2 |
| Trigonometric and hyperbolic | acosh | float32 | ✓ | 2 | 2 | 4 | 2 | 2 | 3 | ≤1 | 2 | 2 | rejects | 2 |
| Trigonometric and hyperbolic | acosh | bfloat16 | ✓ | ✓ | ✓ | 2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | acosh | float16 | ✓ | ≤1 | ≤1 | 2 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | rejects | ≤1 |
| Trigonometric and hyperbolic | acosh | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | acosh | float8 E4M3 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | acosh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | acosh | posit16 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atanh | float64 | ✓ | ≤1 | 2 | 4,503,599,627,370,495 | 2 | 4,503,599,627,370,495 | 2 | ≤1 | 2 | rejects | rejects | 2 |
| Trigonometric and hyperbolic | atanh | float32 | ✓ | ≤1 | 3 | 8,388,607 | 3 | 8,388,607 | 8,388,607 | ≤1 | 8,388,607 | 2 | rejects | 2 |
| Trigonometric and hyperbolic | atanh | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | ✓ | 127 | ✓ | 127 | rejects | rejects | ✓ |
| Trigonometric and hyperbolic | atanh | float16 | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | rejects | ✓ |
| Trigonometric and hyperbolic | atanh | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atanh | float8 E4M3 | ✓ | conv | conv | ≤1 | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Trigonometric and hyperbolic | atanh | TF32 | ✓ | |||||||||||
| Trigonometric and hyperbolic | atanh | posit16 | ✓ | |||||||||||
| Activations | relu | float64 | ✓ | ±0 | ✓ | 4,503,599,627,370,495 | ✓ | 4,503,599,627,370,495 | ✓ | ✓ | ✓ | ±0 | ✓ | ✓ |
| Activations | relu | float32 | ✓ | ±0 | ✓ | 8,388,607 | ✓ | 8,388,607 | ✓ | ✓ | 8,388,607 | ±0 | ✓ | ✓ |
| Activations | relu | bfloat16 | ✓ | ±0 | ✓ | 127 | ✓ | 127 | 127 | ✓ | 127 | rejects | ✓ | ✓ |
| Activations | relu | float16 | ✓ | ±0 | ✓ | ✓ | ✓ | ±0 | ✓ | ±0 | ✓ | ±0 | ✓ | ✓ |
| Activations | relu | float8 E5M2 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Activations | relu | float8 E4M3 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Activations | relu | TF32 | ✓ | |||||||||||
| Activations | leakyReLU | float64 | ✓ | ✓ | ✓ | 4,458,280,719,818,338 | ✓ | 4,503,599,627,370,495 | 201,326,592 | · | ✓ | rejects | 201,326,592 | ✓ |
| Activations | leakyReLU | float32 | ✓ | ✓ | ✓ | 8,382,891 | ✓ | 8,388,607 | 8,382,891 | · | 8,388,607 | ✓ | ✓ | ✓ |
| Activations | leakyReLU | bfloat16 | ✓ | ✓ | ✓ | 127 | ✓ | 127 | 127 | · | rejects | rejects | rejects | ✓ |
| Activations | leakyReLU | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| Activations | leakyReLU | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | leakyReLU | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | leakyReLU | TF32 | ✓ | |||||||||||
| Activations | elu | float64 | ✓ | ≤1 | ≤1 | 4,503,599,627,370,495 | ≤1 | 4,363,961,458,896,588,046 | ≤1 | · | ≤1 | rejects | 4,363,961,458,896,588,046 | 4,494,587,992,567,547,063 |
| Activations | elu | float32 | ✓ | ≤1 | ≤1 | 8,388,607 | ≤1 | 855,612,317 | 8,388,607 | · | 8,388,607 | 855,612,317 | 867,240,451 | 855,612,317 |
| Activations | elu | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 15,104 | 15,104 | · | rejects | rejects | rejects | 15,104 |
| Activations | elu | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | 3,072 | ✓ | · | ✓ | ≤1 | 3,072 | 3,072 |
| Activations | elu | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | elu | float8 E4M3 | ≤1 | ✓ | ✓ | ✓ | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | elu | TF32 | ✓ | |||||||||||
| Activations | sigmoid | float64 | ≤1 | 1,077,003,997,787,060 | 1,077,003,997,787,060 | 4,383,635,548,707,554 | 1,077,003,997,787,060 | 4,383,635,548,707,554 | 1,077,003,997,787,060 | · | 1,077,003,997,787,060 | 4,368,136,721,604,654,146 | 4,368,136,721,604,654,146 | 4,035,191,066,499,671,904 |
| Activations | sigmoid | float32 | ≤1 | 2,080,657 | 2,080,657 | 8,335,948 | 2,080,657 | 8,335,948 | 8,335,948 | · | 8,335,948 | 869,987,759 | 864,023,263 | 4,320,642 |
| Activations | sigmoid | bfloat16 | ≤1 | 24 | 24 | 109 | 24 | 109 | 109 | · | rejects | rejects | 15,227 | 40 |
| Activations | sigmoid | float16 | ≤1 | ≤1 | ≤1 | 255 | 255 | 2 | 255 | · | rejects | 2 | ≤1 | 255 |
| Activations | sigmoid | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | sigmoid | float8 E4M3 | ≤1 | ✓ | ✓ | NaN/∞ | ≤1 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | sigmoid | TF32 | ≤1 | |||||||||||
| Activations | softplus | float64 | ≤1 | 577,689 | 577,689 | 4,336,391,769,732,241 | 2 | 4,336,391,769,732,241 | 7 | ≤1 | 2 | rejects | 4,368,281,163,086,985,607 | 4,037,088,397,506,071,124 |
| Activations | softplus | float32 | ≤1 | ≤1 | 2 | 8,324,889 | 2 | 8,324,889 | 8,324,889 | ≤1 | 8,324,889 | 4 | 864,016,322 | 5,922,629 |
| Activations | softplus | bfloat16 | ≤1 | ✓ | ✓ | 109 | ≤1 | 109 | 109 | ✓ | 109 | rejects | 15,227 | 66 |
| Activations | softplus | float16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,095 | ≤1 |
| Activations | softplus | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Activations | softplus | float8 E4M3 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Activations | softplus | TF32 | ≤1 | |||||||||||
| Activations | silu | float64 | ≤1 | 37,469,013,202,615,485 | 37,469,013,202,615,485 | 46,684,722,066,868,435 | 37,469,013,202,615,485 | 46,684,722,066,868,435 | 37,469,013,202,615,485 | · | 37,469,013,202,615,485 | 4,391,604,047,841,785,956 | 4,391,604,047,841,785,956 | 4,063,996,846,656,982,301 |
| Activations | silu | float32 | 2 | 45,177,546 | 45,177,546 | 61,755,098 | 45,177,546 | 61,755,098 | 61,755,098 | · | 61,755,098 | 906,872,270 | 897,899,166 | 53,785,709 |
| Activations | silu | bfloat16 | 2 | 647 | 647 | 917 | 647 | 917 | 917 | · | rejects | rejects | 15,534 | 733 |
| Activations | silu | float16 | 3 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | · | rejects | NaN/∞ | NaN/∞ | NaN/∞ |
| Activations | silu | float8 E5M2 | 2 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | silu | float8 E4M3 | ≤1 | ✓ | ✓ | NaN/∞ | ✓ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | silu | TF32 | 3 | |||||||||||
| Activations | gelu (tanh) | float64 | 4,054,502,521,738,645,482 | 4,376,493,670,301,884,733 | 4,371,964,506,724,811,734 | 4,359,911,127,104,447,559 | 4,371,964,506,724,811,734 | 4,389,155,536,157,995,163 | 4,371,964,506,724,811,734 | · | 4,371,964,506,724,811,734 | 4,389,155,536,157,995,163 | 4,371,964,506,724,811,734 | 4,371,964,506,724,811,734 |
| Activations | gelu (tanh) | float32 | 783,914,749 | 874,609,976 | 866,371,151 | 890,448,356 | 890,448,356 | 892,260,845 | 892,360,932 | · | 866,371,151 | 1,767,538,089 | 866,371,151 | 866,371,151 |
| Activations | gelu (tanh) | bfloat16 | 15,126 | 13,345 | 13,190 | 15,171 | 13,581 | 15,171 | 15,171 | · | 15,171 | rejects | 15,171 | 15,171 |
| Activations | gelu (tanh) | float16 | 1,179 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | · | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Activations | gelu (tanh) | float8 E5M2 | 42 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | gelu (tanh) | float8 E4M3 | NaN/∞ | ✓ | ✓ | NaN/∞ | ≤1 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | gelu (tanh) | TF32 | 115,867 | |||||||||||
| Activations | gelu (erf) | float64 | · | 4,373,181,763,526,858,262 | 4,374,518,897,643,722,416 | 22,357,023,797,964,722 | 386,221,992,094,816 | 22,357,023,797,964,722 | 386,221,992,094,816 | · | 4,374,518,897,643,722,416 | rejects | 28 | NaN/∞ |
| Activations | gelu (erf) | float32 | · | NaN/∞ | 867,731,000 | 30,136,097 | 827,121 | 30,136,097 | 30,136,097 | · | 867,435,724 | 867,259,968 | 13 | NaN/∞ |
| Activations | gelu (erf) | bfloat16 | · | NaN/∞ | 13,215 | 320 | 6 | 320 | 320 | · | rejects | rejects | 7 | NaN/∞ |
| Activations | gelu (erf) | float16 | · | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | · | rejects | NaN/∞ | NaN/∞ | NaN/∞ |
| Activations | gelu (erf) | float8 E5M2 | · | NaN/∞ | NaN/∞ | rejects | rejects | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | gelu (erf) | float8 E4M3 | · | ✓ | ✓ | rejects | rejects | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | erf | float64 | · | ≤1 | ≤1 | 5,081,767,996,463,980 | ≤1 | 5,081,767,996,463,980 | 3 | · | ≤1 | rejects | ≤1 | 4,506,851,574,766,186,488 |
| Activations | erf | float32 | · | ≤1 | ≤1 | 9,465,529 | 5 | 9,465,529 | 9,465,531 | · | 9,465,529 | ≤1 | ≤1 | 878,465,300 |
| Activations | erf | bfloat16 | · | 13,404 | ✓ | 143 | ✓ | 143 | 143 | · | rejects | rejects | ✓ | 13,404 |
| Activations | erf | float16 | · | 5 | ✓ | ≤1 | ✓ | ✓ | ≤1 | · | rejects | ✓ | ✓ | 5 |
| Activations | erf | float8 E5M2 | · | ✓ | ✓ | ✓ | rejects | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Activations | erf | float8 E4M3 | · | ✓ | ✓ | ✓ | rejects | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Guarded operations | safeLog | float64 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | NaN/∞ | NaN/∞ |
| Guarded operations | safeLog | float32 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Guarded operations | safeLog | bfloat16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ |
| Guarded operations | safeLog | float16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Guarded operations | safeLog | float8 E5M2 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | NaN/∞ | NaN/∞ | rejects |
| Guarded operations | safeLog | float8 E4M3 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | NaN/∞ | NaN/∞ | rejects |
| Guarded operations | safeLog | TF32 | NaN/∞ | |||||||||||
| Guarded operations | safeInv | float64 | ≤1 | ≤1 | ≤1 | 4,434,805,660,482,884 | ≤1 | 4,434,805,660,482,884 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Guarded operations | safeInv | float32 | ≤1 | ≤1 | ≤1 | 8,360,794 | 2 | 8,360,794 | 8,360,794 | ≤1 | 8,360,794 | ≤1 | ≤1 | ≤1 |
| Guarded operations | safeInv | bfloat16 | ≤1 | ≤1 | ≤1 | 127 | ✓ | 128 | 127 | ≤1 | 127 | rejects | ≤1 | ≤1 |
| Guarded operations | safeInv | float16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Guarded operations | safeInv | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | rejects | ≤1 | rejects | rejects | rejects | rejects |
| Guarded operations | safeInv | float8 E4M3 | ✓ | conv | conv | ≤1 | ✓ | rejects | rejects | ≤1 | rejects | rejects | rejects | rejects |
| Guarded operations | safeInv | TF32 | ≤1 | |||||||||||
| Guarded operations | safeDiv | float64 | ≤1 | ≤1 | ≤1 | 94,158,327,512,039,422 | ≤1 | 94,158,327,512,039,422 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Guarded operations | safeDiv | float32 | ≤1 | ≤1 | ≤1 | 189,386,587 | 2 | 189,386,587 | 189,386,587 | ≤1 | 189,386,587 | ≤1 | ≤1 | ≤1 |
| Guarded operations | safeDiv | bfloat16 | ≤1 | ≤1 | ≤1 | 2,926 | ≤1 | 2,926 | 2,926 | ≤1 | 2,926 | rejects | ≤1 | ≤1 |
| Guarded operations | safeDiv | float16 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ |
| Guarded operations | safeDiv | float8 E5M2 | ✓ | ≤1 | ≤1 | NaN/∞ | ≤1 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Guarded operations | safeDiv | float8 E4M3 | ≤1 | conv | conv | NaN/∞ | ≤1 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Guarded operations | safeDiv | TF32 | ≤1 | |||||||||||
| Guarded operations | smoothAbs | float64 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Guarded operations | smoothAbs | float32 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ |
| Guarded operations | smoothAbs | bfloat16 | ≤1 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | NaN/∞ | NaN/∞ |
| Guarded operations | smoothAbs | float16 | 2 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ |
| Guarded operations | smoothAbs | float8 E5M2 | ≤1 | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | rejects | ≤1 | ≤1 | rejects |
| Guarded operations | smoothAbs | float8 E4M3 | ≤1 | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | rejects | ✓ | ✓ | rejects |
| Guarded operations | smoothAbs | TF32 | 2 | |||||||||||
| Guarded operations | nanToNum | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | 4,503,599,627,370,495 | ✓ | ✓ | ✓ | ✓ | ✓ | 178,956,971 |
| Guarded operations | nanToNum | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | 8,388,607 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Guarded operations | nanToNum | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 127 | ✓ | NaN/∞ | 32,639 | rejects | ✓ | ✓ |
| Guarded operations | nanToNum | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Guarded operations | nanToNum | float8 E5M2 | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | ≤1 | ≤1 | rejects |
| Guarded operations | nanToNum | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | ✓ | ✓ | rejects |
| Guarded operations | nanToNum | TF32 | ✓ | |||||||||||
| Guarded operations | clamp | float64 | ✓ | ±0 | ✓ | 4,503,599,627,370,495 | ✓ | 9,214,364,837,600,034,816 | 9,214,364,837,600,034,816 | ±0 | ±0 | ±0 | ±0 | ✓ |
| Guarded operations | clamp | float32 | ✓ | ±0 | ✓ | 8,388,607 | ✓ | 2,130,706,432 | 2,130,706,432 | ±0 | 8,370,869 | ±0 | ±0 | ✓ |
| Guarded operations | clamp | bfloat16 | ✓ | ±0 | ✓ | 127 | ✓ | 32,512 | 32,512 | ✓ | ✓ | rejects | rejects | ✓ |
| Guarded operations | clamp | float16 | ✓ | ±0 | ✓ | ✓ | ✓ | 30,720 | 30,720 | ±0 | ±0 | ±0 | ±0 | ✓ |
| Guarded operations | clamp | float8 E5M2 | ✓ | ±0 | ✓ | ✓ | ✓ | 120 | 120 | ✓ | rejects | ✓ | ✓ | rejects |
| Guarded operations | clamp | float8 E4M3 | ✓ | ±0 | ✓ | ✓ | ✓ | 112 | 112 | ✓ | rejects | ✓ | ✓ | rejects |
| Guarded operations | clamp | TF32 | ✓ | |||||||||||
| Comparisons and selection | max | float64 | ✓ | ±0 | ✓ | 4,503,599,627,370,495 | ✓ | 4,503,599,627,370,495 | ±0 | ±0 | ✓ | ±0 | ±0 | ±0 |
| Comparisons and selection | max | float32 | ✓ | ±0 | ✓ | 8,388,607 | ✓ | 8,388,607 | 16,652,956 | ±0 | 8,388,607 | ±0 | ±0 | ±0 |
| Comparisons and selection | max | bfloat16 | ✓ | ±0 | ✓ | 127 | ✓ | 127 | 252 | ±0 | 127 | rejects | ✓ | ±0 |
| Comparisons and selection | max | float16 | ✓ | ±0 | ✓ | ✓ | ✓ | ±0 | ±0 | ±0 | ✓ | ±0 | ✓ | ±0 |
| Comparisons and selection | max | float8 E5M2 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | max | float8 E4M3 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | max | TF32 | ✓ | |||||||||||
| Comparisons and selection | min | float64 | ✓ | ±0 | ✓ | 4,503,599,627,370,495 | ✓ | 4,503,599,627,370,495 | ±0 | ±0 | ✓ | ±0 | ±0 | ±0 |
| Comparisons and selection | min | float32 | ✓ | ±0 | ✓ | 8,388,607 | ✓ | 8,388,607 | 16,435,590 | ±0 | 8,388,607 | ±0 | ±0 | ±0 |
| Comparisons and selection | min | bfloat16 | ✓ | ±0 | ✓ | 127 | ✓ | 127 | 230 | ±0 | 127 | rejects | ✓ | ±0 |
| Comparisons and selection | min | float16 | ✓ | ±0 | ✓ | ✓ | ✓ | ±0 | ±0 | ±0 | ✓ | ±0 | ✓ | ±0 |
| Comparisons and selection | min | float8 E5M2 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | min | float8 E4M3 | ✓ | ±0 | ✓ | ✓ | ✓ | rejects | rejects | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | min | TF32 | ✓ | |||||||||||
| Comparisons and selection | fmax | float64 | ✓ | ±0 | ✓ | 8,751,155,370,360,414 | ±0 | · | · | ±0 | ✓ | rejects | rejects | rejects |
| Comparisons and selection | fmax | float32 | ✓ | ±0 | ✓ | 16,545,804 | ±0 | · | · | ±0 | 8,388,607 | rejects | rejects | rejects |
| Comparisons and selection | fmax | bfloat16 | ✓ | ±0 | ✓ | 252 | ±0 | · | · | ±0 | 127 | rejects | rejects | rejects |
| Comparisons and selection | fmax | float16 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | ✓ | rejects | rejects | rejects |
| Comparisons and selection | fmax | float8 E5M2 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | fmax | float8 E4M3 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | fmax | TF32 | ✓ | |||||||||||
| Comparisons and selection | fmin | float64 | ✓ | ±0 | ✓ | 5,485,116,409,050,824 | ±0 | · | · | ±0 | ✓ | rejects | rejects | rejects |
| Comparisons and selection | fmin | float32 | ✓ | ±0 | ✓ | 16,531,008 | ±0 | · | · | ±0 | 8,388,607 | rejects | rejects | rejects |
| Comparisons and selection | fmin | bfloat16 | ✓ | ±0 | ✓ | 254 | ±0 | · | · | ±0 | 127 | rejects | rejects | rejects |
| Comparisons and selection | fmin | float16 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | ✓ | rejects | rejects | rejects |
| Comparisons and selection | fmin | float8 E5M2 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | fmin | float8 E4M3 | ✓ | ±0 | ✓ | ±0 | ±0 | · | · | ±0 | rejects | rejects | rejects | rejects |
| Comparisons and selection | fmin | TF32 | ✓ | |||||||||||
| Comparisons and selection | eq | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | eq | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | eq | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | eq | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | eq | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | eq | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | eq | TF32 | ✓ | |||||||||||
| Comparisons and selection | ne | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ne | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ne | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | ne | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ne | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | ne | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | ne | TF32 | ✓ | |||||||||||
| Comparisons and selection | lt | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | lt | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | lt | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | lt | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | lt | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | lt | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | lt | TF32 | ✓ | |||||||||||
| Comparisons and selection | le | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | le | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | le | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | le | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | le | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | le | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | le | TF32 | ✓ | |||||||||||
| Comparisons and selection | gt | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | gt | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | gt | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | gt | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | gt | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | gt | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | gt | TF32 | ✓ | |||||||||||
| Comparisons and selection | ge | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ge | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ge | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Comparisons and selection | ge | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | ge | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | ge | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Comparisons and selection | ge | TF32 | ✓ | |||||||||||
| Comparisons and selection | isNaN | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isNaN | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isNaN | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isNaN | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isNaN | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isNaN | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isNaN | TF32 | ✓ | |||||||||||
| Comparisons and selection | isInf | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isInf | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isInf | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isInf | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isInf | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isInf | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isInf | TF32 | ✓ | |||||||||||
| Comparisons and selection | isFinite | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isFinite | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isFinite | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isFinite | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | isFinite | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isFinite | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | ✓ | ✓ | rejects |
| Comparisons and selection | isFinite | TF32 | ✓ | |||||||||||
| Comparisons and selection | select | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | select | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | select | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Comparisons and selection | select | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Comparisons and selection | select | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Comparisons and selection | select | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Comparisons and selection | select | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | reduce sum | float64 | ≤1 | 128 | 256 | 150 | 234 | 812 | 1,324 | 812 | ≤1 | ≤1 | ≤1 | ≤1 |
| Reductions, scans and sorting | reduce sum | float32 | ≤1 | 400 | 384 | 65 | 21 | 172 | 159 | 169 | ≤1 | ✓ | ✓ | ≤1 |
| Reductions, scans and sorting | reduce sum | bfloat16 | ≤1 | ≤1 | ±0 | ✓ | ✓ | ✓ | ✓ | 168 | ✓ | rejects | ✓ | ≤1 |
| Reductions, scans and sorting | reduce sum | float16 | NaN/∞ | ±0 | ±0 | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | ✓ | ✓ | NaN/∞ |
| Reductions, scans and sorting | reduce sum | float8 E5M2 | NaN/∞ | ±0 | ±0 | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce sum | float8 E4M3 | ✓ | ±0 | ±0 | 152 | ✓ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce sum | TF32 | 2 | |||||||||||
| Reductions, scans and sorting | reduce prod | float64 | ✓ | 9 | 11 | 6 | 7 | 9 | 8 | 10 | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce prod | float32 | ✓ | 8 | 8 | 9 | 6 | 8 | 7 | 10 | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce prod | bfloat16 | ≤1 | 7 | ✓ | ✓ | ✓ | 9 | 8 | 8 | ✓ | rejects | rejects | ≤1 |
| Reductions, scans and sorting | reduce prod | float16 | ✓ | NaN/∞ | ≤1 | ✓ | ✓ | 8 | 9 | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce prod | float8 E5M2 | ✓ | ✓ | ✓ | 14 | NaN/∞ | rejects | rejects | 11 | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce prod | float8 E4M3 | ≤1 | conv | conv | 13 | ≤1 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce prod | TF32 | ≤1 | |||||||||||
| Reductions, scans and sorting | reduce max | float64 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce max | float32 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce max | bfloat16 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Reductions, scans and sorting | reduce max | float16 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce max | float8 E5M2 | ✓ | ±0 | ±0 | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce max | float8 E4M3 | ✓ | ±0 | ±0 | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce max | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | reduce min | float64 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce min | float32 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce min | bfloat16 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Reductions, scans and sorting | reduce min | float16 | ✓ | ±0 | ±0 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | reduce min | float8 E5M2 | ✓ | ±0 | ±0 | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce min | float8 E4M3 | ✓ | ±0 | ±0 | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | reduce min | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | mean | float64 | ≤1 | 9,007,199,254,740,993 | 512 | 23 | 23 | 59 | 66 | 162 | ≤1 | ≤1 | ≤1 | ≤1 |
| Reductions, scans and sorting | mean | float32 | ≤1 | 16,777,217 | 536 | 109 | 117 | 330 | 1,718 | 2,378 | ≤1 | ✓ | ✓ | ≤1 |
| Reductions, scans and sorting | mean | bfloat16 | ≤1 | 257 | ±0 | ✓ | ✓ | ✓ | ✓ | 499 | ✓ | rejects | ✓ | ≤1 |
| Reductions, scans and sorting | mean | float16 | NaN/∞ | ≤1 | ±0 | ✓ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ | NaN/∞ |
| Reductions, scans and sorting | mean | float8 E5M2 | NaN/∞ | ±0 | ±0 | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | mean | float8 E4M3 | ✓ | ±0 | ±0 | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | mean | TF32 | 2 | |||||||||||
| Reductions, scans and sorting | cumsum | float64 | ≤1 | 2,372,847 | 477,969 | 14,916 | 14,916 | 2,339 | 2,013 | 2,339 | ≤1 | ≤1 | ≤1 | ≤1 |
| Reductions, scans and sorting | cumsum | float32 | ≤1 | ✓ | 62,528 | 81,034 | 81,034 | 16,082 | 6,866 | 16,082 | ≤1 | ≤1 | ≤1 | ≤1 |
| Reductions, scans and sorting | cumsum | bfloat16 | ≤1 | ≤1 | 34,451 | 32,412 | 31,990 | 32,890 | 32,418 | 32,890 | rejects | rejects | rejects | ≤1 |
| Reductions, scans and sorting | cumsum | float16 | NaN/∞ | 137 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ |
| Reductions, scans and sorting | cumsum | float8 E5M2 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cumsum | float8 E4M3 | ✓ | conv | conv | 176 | 150 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cumsum | TF32 | 2 | |||||||||||
| Reductions, scans and sorting | cumprod | float64 | ✓ | 10 | 9 | 7 | 7 | 10 | 13 | 10 | ≤1 | ✓ | rejects | ✓ |
| Reductions, scans and sorting | cumprod | float32 | ✓ | ✓ | 12 | 9 | 9 | 11 | 12 | 11 | ≤1 | ✓ | rejects | ✓ |
| Reductions, scans and sorting | cumprod | bfloat16 | ≤1 | ✓ | 11 | 9 | 3 | 10 | 10 | 10 | rejects | rejects | rejects | ≤1 |
| Reductions, scans and sorting | cumprod | float16 | ✓ | ≤1 | NaN/∞ | 8 | 8 | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | ✓ | rejects | ✓ |
| Reductions, scans and sorting | cumprod | float8 E5M2 | ✓ | ✓ | ✓ | 10 | 2 | rejects | rejects | 11 | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cumprod | float8 E4M3 | ≤1 | conv | conv | 9 | NaN/∞ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cumprod | TF32 | ≤1 | |||||||||||
| Reductions, scans and sorting | cummax | float64 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummax | float32 | ✓ | ±0 | ±0 | 8,278,312 | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummax | bfloat16 | ✓ | ±0 | ±0 | 74 | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummax | float16 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummax | float8 E5M2 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cummax | float8 E4M3 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cummax | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | cummin | float64 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummin | float32 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummin | bfloat16 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummin | float16 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | cummin | float8 E5M2 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cummin | float8 E4M3 | ✓ | ±0 | ±0 | ✓ | ✓ | · | · | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | cummin | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | argmax | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmax | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmax | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Reductions, scans and sorting | argmax | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmax | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | argmax | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | argmax | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | argmin | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmin | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmin | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Reductions, scans and sorting | argmin | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | argmin | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | argmin | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | argmin | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | sort | float64 | ✓ | ✓ | ✓ | 4,249,066,248,055,019 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | sort | float32 | ✓ | ✓ | ✓ | 12,760,704 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | sort | bfloat16 | ✓ | ✓ | ✓ | 227 | ✓ | ✓ | ✓ | ✓ | rejects | rejects | rejects | ✓ |
| Reductions, scans and sorting | sort | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Reductions, scans and sorting | sort | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | sort | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | sort | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | sort desc | float64 | ✓ | ✓ | ✓ | 4,277,672,943,617,209 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects |
| Reductions, scans and sorting | sort desc | float32 | ✓ | ✓ | ✓ | 13,325,040 | ±0 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects |
| Reductions, scans and sorting | sort desc | bfloat16 | ✓ | ✓ | ✓ | 248 | ±0 | ✓ | ✓ | ✓ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | sort desc | float16 | ✓ | ✓ | ✓ | ±0 | ±0 | NaN/∞ | NaN/∞ | ✓ | ✓ | ✓ | ✓ | rejects |
| Reductions, scans and sorting | sort desc | float8 E5M2 | ✓ | ✓ | ✓ | ±0 | ±0 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | sort desc | float8 E4M3 | ✓ | ✓ | ✓ | ±0 | ±0 | rejects | rejects | NaN/∞ | rejects | rejects | rejects | rejects |
| Reductions, scans and sorting | sort desc | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | topk | float64 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topk | float32 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topk | bfloat16 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | conv | rejects | rejects | rejects | conv |
| Reductions, scans and sorting | topk | float16 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topk | float8 E5M2 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | conv | · | ≤1 | ≤1 | · |
| Reductions, scans and sorting | topk | float8 E4M3 | ✓ | conv | conv | ✓ | NaN/∞ | 39 | NaN/∞ | conv | · | 39 | 39 | · |
| Reductions, scans and sorting | topk | TF32 | ✓ | |||||||||||
| Reductions, scans and sorting | topKMask | float64 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topKMask | float32 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topKMask | bfloat16 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | rejects | rejects | rejects | conv |
| Reductions, scans and sorting | topKMask | float16 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | conv | ✓ | ✓ | conv |
| Reductions, scans and sorting | topKMask | float8 E5M2 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | · | ✓ | ✓ | · |
| Reductions, scans and sorting | topKMask | float8 E4M3 | ✓ | conv | ✓ | ✓ | ✓ | ✓ | ✓ | conv | · | ✓ | ✓ | · |
| Reductions, scans and sorting | topKMask | TF32 | ✓ | |||||||||||
| Softmax and losses | softmax | float64 | 3 | 131 | 133 | 259 | 257 | 19 | 18 | · | 3 | 3 | 434,021,499 | 3,549,847,431 |
| Softmax and losses | softmax | float32 | ≤1 | 66 | 66 | 8,374,130 | 67 | 19 | 19 | · | ≤1 | 2 | ≤1 | 7 |
| Softmax and losses | softmax | bfloat16 | ✓ | ≤1 | ≤1 | 123 | 57 | 18 | ≤1 | · | ≤1 | rejects | ✓ | ≤1 |
| Softmax and losses | softmax | float16 | 2 | ≤1 | ≤1 | 9 | 9 | 9 | ≤1 | · | 3 | ✓ | ✓ | 2 |
| Softmax and losses | softmax | float8 E5M2 | 3 | ✓ | ✓ | 12 | ≤1 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Softmax and losses | softmax | float8 E4M3 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Softmax and losses | softmax | TF32 | 2 | |||||||||||
| Softmax and losses | logSoftmax | float64 | ≤1 | 4,368,198,740,152,583,028 | 4,368,198,740,152,583,028 | 3,410,329,462,066,086 | 3,410,329,462,066,086 | 6,922,144 | 6,922,144 | · | 6,922,144 | 6,922,144 | 4,494,691,807,354,678,966 | 3,619,950,922 |
| Softmax and losses | logSoftmax | float32 | ≤1 | 866,406,280 | 865,235,712 | 855,823,124 | 855,823,124 | 855,823,124 | 855,823,124 | · | 855,823,124 | 855,823,124 | 855,823,124 | 855,823,124 |
| Softmax and losses | logSoftmax | bfloat16 | ✓ | 15,231 | 13,242 | 15,146 | 15,146 | 13,059 | 13,059 | · | 13,059 | rejects | rejects | 16,269 |
| Softmax and losses | logSoftmax | float16 | ≤1 | 4,096 | 2 | 1,832 | 1,832 | 3 | ≤1 | · | 27 | ≤1 | ≤1 | 15,461 |
| Softmax and losses | logSoftmax | float8 E5M2 | ≤1 | ≤1 | ≤1 | 56 | 17 | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Softmax and losses | logSoftmax | float8 E4M3 | ≤1 | ≤1 | ≤1 | NaN/∞ | NaN/∞ | rejects | rejects | · | rejects | rejects | rejects | rejects |
| Softmax and losses | logSoftmax | TF32 | ✓ | |||||||||||
| Softmax and losses | maskedSoftmax | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 328,622,155 | 3,549,847,431 |
| Softmax and losses | maskedSoftmax | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 7 |
| Softmax and losses | maskedSoftmax | bfloat16 | ≤1 | conv | conv | ≤1 | ≤1 | ≤1 | conv | ≤1 | conv | rejects | conv | ≤1 |
| Softmax and losses | maskedSoftmax | float16 | ≤1 | conv | conv | ≤1 | ≤1 | ≤1 | conv | ≤1 | ≤1 | conv | conv | ≤1 |
| Softmax and losses | maskedSoftmax | float8 E5M2 | ≤1 | conv | conv | ≤1 | ≤1 | conv | conv | ≤1 | · | conv | conv | · |
| Softmax and losses | maskedSoftmax | float8 E4M3 | ≤1 | conv | conv | NaN/∞ | ≤1 | conv | conv | NaN/∞ | · | conv | conv | · |
| Softmax and losses | maskedSoftmax | TF32 | ≤1 | |||||||||||
| Softmax and losses | crossEntropy | float64 | ≤1 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 2 | 342,958,508 | 88,734,404 |
| Softmax and losses | crossEntropy | float32 | ≤1 | 2 | ≤1 | 2 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | 2 | 456 | 456 |
| Softmax and losses | crossEntropy | bfloat16 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | rejects | rejects | 124 |
| Softmax and losses | crossEntropy | float16 | ✓ | ≤1 | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | 996 |
| Softmax and losses | crossEntropy | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Softmax and losses | crossEntropy | float8 E4M3 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Softmax and losses | crossEntropy | TF32 | ✓ | |||||||||||
| Softmax and losses | crossEntropyProbs | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | crossEntropyProbs | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | crossEntropyProbs | bfloat16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ✓ | rejects | rejects | ≤1 |
| Softmax and losses | crossEntropyProbs | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | crossEntropyProbs | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Softmax and losses | crossEntropyProbs | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Softmax and losses | crossEntropyProbs | TF32 | ≤1 | |||||||||||
| Softmax and losses | binaryCrossEntropy | float64 | ✓ | ✓ | ✓ | 74,078 | 74,078 | 74,078 | 74,078 | 74,078 | 74,078 | 74,078 | 74,078 | ✓ |
| Softmax and losses | binaryCrossEntropy | float32 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 |
| Softmax and losses | binaryCrossEntropy | bfloat16 | ≤1 | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | rejects | ✓ |
| Softmax and losses | binaryCrossEntropy | float16 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | ✓ |
| Softmax and losses | binaryCrossEntropy | float8 E5M2 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Softmax and losses | binaryCrossEntropy | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | · | conv | conv | · |
| Softmax and losses | binaryCrossEntropy | TF32 | ✓ | |||||||||||
| Softmax and losses | mseLoss | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | mseLoss | float32 | ≤1 | ≤1 | ✓ | ≤1 | ✓ | ≤1 | ✓ | ≤1 | ✓ | ✓ | ≤1 | ≤1 |
| Softmax and losses | mseLoss | bfloat16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 | ≤1 |
| Softmax and losses | mseLoss | float16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | mseLoss | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | ≤1 | ≤1 | · |
| Softmax and losses | mseLoss | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | ✓ | · | conv | conv | · |
| Softmax and losses | mseLoss | TF32 | ≤1 | |||||||||||
| Softmax and losses | maeLoss | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | maeLoss | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | maeLoss | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | rejects | ✓ | ≤1 |
| Softmax and losses | maeLoss | float16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ |
| Softmax and losses | maeLoss | float8 E5M2 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Softmax and losses | maeLoss | float8 E4M3 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Softmax and losses | maeLoss | TF32 | ✓ | |||||||||||
| Softmax and losses | huberLoss | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | huberLoss | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | huberLoss | bfloat16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | rejects | ≤1 |
| Softmax and losses | huberLoss | float16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | NaN/∞ | NaN/∞ |
| Softmax and losses | huberLoss | float8 E5M2 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Softmax and losses | huberLoss | float8 E4M3 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Softmax and losses | huberLoss | TF32 | ≤1 | |||||||||||
| Softmax and losses | hingeLoss | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | hingeLoss | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | hingeLoss | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Softmax and losses | hingeLoss | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | hingeLoss | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Softmax and losses | hingeLoss | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Softmax and losses | hingeLoss | TF32 | ✓ | |||||||||||
| Softmax and losses | poissonLoss | float64 | ≤1 | ≤1 | ≤1 | 4 | ≤1 | 4 | ≤1 | ≤1 | ≤1 | 4 | ≤1 | 3,993,944,752 |
| Softmax and losses | poissonLoss | float32 | ≤1 | ≤1 | 2 | ≤1 | 2 | ≤1 | ✓ | 4 | ✓ | ≤1 | ✓ | 8 |
| Softmax and losses | poissonLoss | bfloat16 | 2 | 4 | 4 | 4 | 4 | 4 | 4 | 2 | 4 | rejects | 4 | 2 |
| Softmax and losses | poissonLoss | float16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ |
| Softmax and losses | poissonLoss | float8 E5M2 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ≤1 | ≤1 | · |
| Softmax and losses | poissonLoss | float8 E4M3 | ✓ | conv | conv | ✓ | 4 | ✓ | ✓ | ✓ | · | conv | conv | · |
| Softmax and losses | poissonLoss | TF32 | 3 | |||||||||||
| Softmax and losses | logCoshLoss | float64 | ≤1 | NaN/∞ | NaN/∞ | 6 | 6 | 4,476,679,601,556,291,584 | 4,476,679,601,556,291,584 | NaN/∞ | NaN/∞ | rejects | rejects | 4,476,679,601,556,291,584 |
| Softmax and losses | logCoshLoss | float32 | ≤1 | NaN/∞ | NaN/∞ | 5 | 5 | ≤1 | 9 | NaN/∞ | NaN/∞ | NaN/∞ | rejects | ≤1 |
| Softmax and losses | logCoshLoss | bfloat16 | ✓ | NaN/∞ | NaN/∞ | 14 | 10 | 10 | 10 | NaN/∞ | NaN/∞ | rejects | rejects | 14 |
| Softmax and losses | logCoshLoss | float16 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | rejects | NaN/∞ |
| Softmax and losses | logCoshLoss | float8 E5M2 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | NaN/∞ | rejects | · |
| Softmax and losses | logCoshLoss | float8 E4M3 | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | NaN/∞ | rejects | · |
| Softmax and losses | logCoshLoss | TF32 | ✓ | |||||||||||
| Softmax and losses | cosineLoss | float64 | ≤1 | 3 | 3 | 3 | 3 | 3 | 3 | 4,372,995,238,176,751,616 | 4,372,995,238,176,751,616 | 4,372,995,238,176,751,616 | 4,372,995,238,176,751,616 | 4,372,995,238,176,751,616 |
| Softmax and losses | cosineLoss | float32 | ✓ | 864,026,624 | 864,026,624 | 864,026,624 | 864,026,624 | 864,026,624 | 872,415,232 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Softmax and losses | cosineLoss | bfloat16 | ≤1 | 15,360 | 15,360 | 15,424 | 15,424 | 15,424 | 15,424 | 15,104 | 15,104 | rejects | rejects | 15,232 |
| Softmax and losses | cosineLoss | float16 | ≤1 | 15,360 | 15,360 | 15,360 | 15,360 | 15,360 | 15,360 | NaN/∞ | NaN/∞ | ✓ | NaN/∞ | NaN/∞ |
| Softmax and losses | cosineLoss | float8 E5M2 | ✓ | ✓ | ✓ | 60 | 60 | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Softmax and losses | cosineLoss | float8 E4M3 | ✓ | ✓ | ✓ | 3 | 3 | ✓ | ✓ | 4 | · | ✓ | ✓ | · |
| Softmax and losses | cosineLoss | TF32 | ≤1 | |||||||||||
| Softmax and losses | distill | float64 | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 3,356,194 | 3,714,349 |
| Softmax and losses | distill | float32 | ≤1 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | distill | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Softmax and losses | distill | float16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Softmax and losses | distill | float8 E5M2 | ✓ | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Softmax and losses | distill | float8 E4M3 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Softmax and losses | distill | TF32 | ≤1 | |||||||||||
| Layers | linear | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects |
| Layers | linear | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 6,552 | ≤1 | ≤1 | ≤1 | 6,552 | ≤1 |
| Layers | linear | bfloat16 | 16,256 | ✓ | ✓ | 16,256 | 16,256 | 640 | 16,256 | ✓ | 16,256 | rejects | ✓ | rejects |
| Layers | linear | float16 | 15,360 | ✓ | ≤1 | 15,360 | 15,360 | 15,360 | 15,360 | 15,360 | 15,360 | ✓ | ✓ | rejects |
| Layers | linear | float8 E5M2 | 60 | ✓ | ✓ | 60 | 60 | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Layers | linear | float8 E4M3 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | linear | TF32 | 130,048 | |||||||||||
| Layers | matmul | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Layers | matmul | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 8,388,608 | ≤1 | ≤1 | ≤1 | 8,388,608 | ≤1 |
| Layers | matmul | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Layers | matmul | float16 | NaN/∞ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | matmul | float8 E5M2 | NaN/∞ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Layers | matmul | float8 E4M3 | NaN/∞ | conv | conv | ✓ | NaN/∞ | ✓ | ✓ | ✓ | · | conv | conv | · |
| Layers | matmul | TF32 | ✓ | |||||||||||
| Layers | scaledMatmul | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Layers | scaledMatmul | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 8,388,608 | ≤1 | ≤1 | ≤1 | 8,388,608 | ≤1 |
| Layers | scaledMatmul | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Layers | scaledMatmul | float16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 |
| Layers | scaledMatmul | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | 4 | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Layers | scaledMatmul | float8 E4M3 | NaN/∞ | conv | conv | ≤1 | NaN/∞ | ✓ | ✓ | ✓ | · | conv | conv | · |
| Layers | scaledMatmul | TF32 | ≤1 | |||||||||||
| Layers | contract | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Layers | contract | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 2,848 | ≤1 | ≤1 | ≤1 | 2,848 | ≤1 |
| Layers | contract | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Layers | contract | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | contract | float8 E5M2 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | contract | float8 E4M3 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | contract | TF32 | ✓ | |||||||||||
| Layers | conv | float64 | 2 | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 37,449 | rejects | 2 | 1,431,655,766 |
| Layers | conv | float32 | 2 | 2 | 2 | 2 | 2 | 2 | 5,462 | 2 | 37,449 | 2 | 2 | 2 |
| Layers | conv | bfloat16 | 2 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 11,410 | rejects | ≤1 | ≤1 |
| Layers | conv | float16 | 2 | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 7,314 | ✓ | ≤1 | ≤1 |
| Layers | conv | float8 E5M2 | 2 | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Layers | conv | float8 E4M3 | 3 | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Layers | conv | TF32 | 2 | |||||||||||
| Layers | convTranspose | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 1,170 | rejects | ≤1 | rejects |
| Layers | convTranspose | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 5,461 | ≤1 | 7,022 | ≤1 | ≤1 | ≤1 |
| Layers | convTranspose | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Layers | convTranspose | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | convTranspose | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | convTranspose | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | convTranspose | TF32 | ✓ | |||||||||||
| Layers | pool | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 |
| Layers | pool | float32 | ✓ | ✓ | ✓ | ≤1 | ≤1 | ✓ | ≤1 | ✓ | ✓ | ✓ | ≤1 | ≤1 |
| Layers | pool | bfloat16 | ≤1 | ✓ | ✓ | ≤1 | ✓ | ≤1 | ✓ | ≤1 | ✓ | rejects | ✓ | ≤1 |
| Layers | pool | float16 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ |
| Layers | pool | float8 E5M2 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ≤1 | ≤1 | · |
| Layers | pool | float8 E4M3 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | conv | ✓ | · |
| Layers | pool | TF32 | ≤1 | |||||||||||
| Layers | smoothMaxPool | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 15,062,304 |
| Layers | smoothMaxPool | float32 | ✓ | ✓ | ✓ | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | smoothMaxPool | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ |
| Layers | smoothMaxPool | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | smoothMaxPool | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | smoothMaxPool | float8 E4M3 | NaN/∞ | ✓ | ✓ | NaN/∞ | NaN/∞ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Layers | smoothMaxPool | TF32 | ✓ | |||||||||||
| Layers | layerNorm | float64 | 2 | 2 | 2 | 2 | 2 | 1,651,292 | 1,651,292 | 2 | 2 | 70,268,339 | 1,861,942,842 | 906,188,420 |
| Layers | layerNorm | float32 | 2 | 2 | 2 | 87,933,158 | 87,933,156 | 1,973,543 | 1,973,543 | 2 | 2 | 2 | 3 | 2 |
| Layers | layerNorm | bfloat16 | ≤1 | 15,776 | ✓ | ≤1 | ≤1 | 16,256 | 16,256 | ≤1 | ✓ | ✓ | ✓ | ≤1 |
| Layers | layerNorm | float16 | 3 | 6,656 | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ≤1 | ≤1 | ✓ | ✓ | ≤1 |
| Layers | layerNorm | float8 E5M2 | ≤1 | ✓ | ✓ | NaN/∞ | NaN/∞ | 2 | 2 | 3 | · | ✓ | ✓ | · |
| Layers | layerNorm | float8 E4M3 | ≤1 | ✓ | ✓ | 3 | ≤1 | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Layers | layerNorm | TF32 | 3 | |||||||||||
| Layers | batchNorm | float64 | 2 | ≤1 | ≤1 | ≤1 | ≤1 | 69,602 | 69,602 | ≤1 | ≤1 | 69,602 | rejects | ≤1 |
| Layers | batchNorm | float32 | ≤1 | ≤1 | 2 | 77,645,022 | 77,645,021 | 9,495 | 9,495 | 2 | 2 | 9,495 | rejects | 2 |
| Layers | batchNorm | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 15,821 | 15,821 | ✓ | ✓ | rejects | rejects | ✓ |
| Layers | batchNorm | float16 | ≤1 | ✓ | ✓ | NaN/∞ | NaN/∞ | NaN/∞ | NaN/∞ | ✓ | ✓ | 410 | rejects | ✓ |
| Layers | batchNorm | float8 E5M2 | ✓ | ✓ | ✓ | NaN/∞ | NaN/∞ | 2 | 2 | ≤1 | · | 2 | rejects | · |
| Layers | batchNorm | float8 E4M3 | ≤1 | rejects | rejects | ≤1 | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Layers | batchNorm | TF32 | ≤1 | |||||||||||
| Layers | batchNormRunning | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 60,902,529 | 60,902,529 | ≤1 |
| Layers | batchNormRunning | float32 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 2 | ≤1 |
| Layers | batchNormRunning | bfloat16 | ≤1 | ✓ | ✓ | ✓ | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | rejects | rejects | ≤1 |
| Layers | batchNormRunning | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | batchNormRunning | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Layers | batchNormRunning | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | batchNormRunning | TF32 | ≤1 | |||||||||||
| Layers | embedding | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | embedding | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | embedding | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | embedding | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Layers | embedding | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Layers | embedding | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Layers | embedding | TF32 | ✓ | |||||||||||
| Layers | dropout | float64 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Layers | dropout | float32 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Layers | dropout | bfloat16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Layers | dropout | float16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Layers | dropout | float8 E5M2 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Layers | dropout | float8 E4M3 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Layers | dropout | TF32 | rand | |||||||||||
| Attention, scans and transforms | attention | float64 | ≤1 | 2 | 2 | 442,878,341 | 453,268,174 | ≤1 | ≤1 | ≤1 | ≤1 | 232,310,360 | rejects | 329,441,711 |
| Attention, scans and transforms | attention | float32 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | 7,517 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Attention, scans and transforms | attention | bfloat16 | 2 | ✓ | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | rejects | ≤1 | ≤1 |
| Attention, scans and transforms | attention | float16 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Attention, scans and transforms | attention | float8 E5M2 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Attention, scans and transforms | attention | float8 E4M3 | ≤1 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Attention, scans and transforms | attention | TF32 | ≤1 | |||||||||||
| Attention, scans and transforms | attnFromScores | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 786,302,818 | 206,740,675 |
| Attention, scans and transforms | attnFromScores | float32 | ≤1 | ≤1 | 2 | ≤1 | 2 | ≤1 | 2,857 | ≤1 | 2 | ≤1 | 2,857 | ≤1 |
| Attention, scans and transforms | attnFromScores | bfloat16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 | ≤1 |
| Attention, scans and transforms | attnFromScores | float16 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 |
| Attention, scans and transforms | attnFromScores | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Attention, scans and transforms | attnFromScores | float8 E4M3 | ✓ | ✓ | ✓ | NaN/∞ | ✓ | ✓ | ✓ | NaN/∞ | · | ✓ | ✓ | · |
| Attention, scans and transforms | attnFromScores | TF32 | ≤1 | |||||||||||
| Attention, scans and transforms | multiheadAttn | float64 | 1,024 | 1,024 | 1,024 | 596,314,433 | 933,134,241 | 1,023 | 1,024 | 1,024 | 1,024 | 1,300,955,194 | rejects | 1,022,160,305 |
| Attention, scans and transforms | multiheadAttn | float32 | 1,024 | 1,024 | 1,024 | 1,024 | 1,024 | 1,024 | 41,317,067 | 1,023 | 1,024 | 1,024 | 41,317,067 | 1,023 |
| Attention, scans and transforms | multiheadAttn | bfloat16 | 396 | ≤1 | ≤1 | ≤1 | ≤1 | 3 | ≤1 | ✓ | ≤1 | rejects | ≤1 | 2 |
| Attention, scans and transforms | multiheadAttn | float16 | 2,965 | ≤1 | ≤1 | ≤1 | 2 | 3 | 2 | 3 | 3 | 2 | ≤1 | 2 |
| Attention, scans and transforms | multiheadAttn | float8 E5M2 | 77 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Attention, scans and transforms | multiheadAttn | float8 E4M3 | 17 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Attention, scans and transforms | multiheadAttn | TF32 | 5,043 | |||||||||||
| Attention, scans and transforms | selectiveScan | float64 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Attention, scans and transforms | selectiveScan | float32 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Attention, scans and transforms | selectiveScan | bfloat16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | rejects | ≤1 | ≤1 |
| Attention, scans and transforms | selectiveScan | float16 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Attention, scans and transforms | selectiveScan | float8 E5M2 | ≤1 | ✓ | ✓ | ≤1 | ≤1 | ✓ | ✓ | ≤1 | · | ✓ | ✓ | · |
| Attention, scans and transforms | selectiveScan | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Attention, scans and transforms | selectiveScan | TF32 | ≤1 | |||||||||||
| Attention, scans and transforms | rfft | float64 | 5 | 3 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,433,512,358,169,542,656 | rejects | 463,817,785 |
| Attention, scans and transforms | rfft | float32 | 11 | ≤1 | ≤1 | 2 | ≤1 | ≤1 | ≤1 | ✓ | ≤1 | 986,185,728 | rejects | ≤1 |
| Attention, scans and transforms | rfft | bfloat16 | 7 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 15,016 | rejects | ✓ |
| Attention, scans and transforms | rfft | float16 | 8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 5,952 | rejects | ✓ |
| Attention, scans and transforms | rfft | float8 E5M2 | 8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | 21 | rejects | · |
| Attention, scans and transforms | rfft | float8 E4M3 | 10 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Attention, scans and transforms | rfft | TF32 | 8 | |||||||||||
| Attention, scans and transforms | irfft | float64 | 4 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 4,370,293,078,494,281,728 | rejects | 852,222,391 |
| Attention, scans and transforms | irfft | float32 | 4 | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 873,254,093 | rejects | 2 |
| Attention, scans and transforms | irfft | bfloat16 | 2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 13,286 | rejects | ✓ |
| Attention, scans and transforms | irfft | float16 | 13 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 3 | rejects | ✓ |
| Attention, scans and transforms | irfft | float8 E5M2 | 51 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ±0 | rejects | · |
| Attention, scans and transforms | irfft | float8 E4M3 | 54 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ±0 | rejects | · |
| Attention, scans and transforms | irfft | TF32 | 13 | |||||||||||
| Movement and indexing | detach | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | detach | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | detach | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | detach | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | detach | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | rejects | ✓ | ✓ | rejects |
| Movement and indexing | detach | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | rejects | ✓ | ✓ | rejects |
| Movement and indexing | detach | TF32 | ✓ | |||||||||||
| Movement and indexing | reshape | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | reshape | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | reshape | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | reshape | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | reshape | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | reshape | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | reshape | TF32 | ✓ | |||||||||||
| Movement and indexing | permute | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | permute | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | permute | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | permute | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | permute | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ≤1 | · |
| Movement and indexing | permute | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | permute | TF32 | ✓ | |||||||||||
| Movement and indexing | broadcast | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | broadcast | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | broadcast | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Movement and indexing | broadcast | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | broadcast | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | broadcast | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | broadcast | TF32 | ✓ | |||||||||||
| Movement and indexing | fullLike | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | fullLike | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | fullLike | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Movement and indexing | fullLike | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | fullLike | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | fullLike | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | fullLike | TF32 | ✓ | |||||||||||
| Movement and indexing | flip | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | flip | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | flip | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | flip | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | flip | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | flip | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | flip | TF32 | ✓ | |||||||||||
| Movement and indexing | slice | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | slice | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | slice | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | slice | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | slice | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | slice | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | slice | TF32 | ✓ | |||||||||||
| Movement and indexing | pad | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | pad | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | pad | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ | ✓ |
| Movement and indexing | pad | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | pad | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | pad | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | pad | TF32 | ✓ | |||||||||||
| Movement and indexing | cat | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cat | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cat | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cat | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cat | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | cat | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | cat | TF32 | ✓ | |||||||||||
| Movement and indexing | gather | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | gather | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | gather | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | gather | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | gather | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | gather | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | gather | TF32 | ✓ | |||||||||||
| Movement and indexing | scatter | float64 | ≤1 | ≤1 | 4,503,599,627,370,496 | ≤1 | ≤1 | ≤1 | 4,503,599,627,370,496 | ≤1 | 4,503,599,627,370,496 | ≤1 | 4,503,599,627,370,496 | ≤1 |
| Movement and indexing | scatter | float32 | ✓ | ✓ | 8,388,608 | ✓ | 8,388,608 | ✓ | 8,388,608 | ✓ | 8,388,608 | ✓ | 8,388,608 | ✓ |
| Movement and indexing | scatter | bfloat16 | ✓ | ✓ | 128 | ✓ | ✓ | ✓ | ✓ | ✓ | 128 | ✓ | 128 | ✓ |
| Movement and indexing | scatter | float16 | ≤1 | ✓ | 1,024 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | 1,024 | ✓ | 1,024 | ≤1 |
| Movement and indexing | scatter | float8 E5M2 | ✓ | ✓ | 4 | ✓ | ✓ | ✓ | 4 | ✓ | · | ≤1 | 4 | · |
| Movement and indexing | scatter | float8 E4M3 | ✓ | ✓ | 8 | ✓ | ✓ | ✓ | 8 | ✓ | · | ✓ | 8 | · |
| Movement and indexing | scatter | TF32 | ≤1 | |||||||||||
| Movement and indexing | indexAt | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indexAt | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indexAt | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indexAt | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indexAt | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ≤1 | ≤1 | · |
| Movement and indexing | indexAt | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | indexAt | TF32 | ✓ | |||||||||||
| Movement and indexing | indices | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indices | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indices | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indices | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | indices | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | indices | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Movement and indexing | indices | TF32 | ✓ | |||||||||||
| Movement and indexing | encodeIndex | float64 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | float32 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | bfloat16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | float16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | float8 E5M2 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | float8 E4M3 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | encodeIndex | TF32 | ✓ | |||||||||||
| Movement and indexing | decodeIndex | float64 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | float32 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | bfloat16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | float16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | float8 E5M2 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | float8 E4M3 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Movement and indexing | decodeIndex | TF32 | ✓ | |||||||||||
| Movement and indexing | cast | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cast | float32 | ✓ | ✓ | ✓ | 8,381,831 | ✓ | ✓ | ✓ | ✓ | 8,388,608 | ✓ | ✓ | ✓ |
| Movement and indexing | cast | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 | ≤1 |
| Movement and indexing | cast | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Movement and indexing | cast | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | NaN/∞ | ✓ | rejects |
| Movement and indexing | cast | float8 E4M3 | ✓ | conv | conv | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | conv | conv | rejects |
| Movement and indexing | cast | TF32 | ✓ | |||||||||||
| Movement and indexing | bitcast | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Movement and indexing | bitcast | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Movement and indexing | bitcast | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Movement and indexing | bitcast | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Movement and indexing | bitcast | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | · | rejects | rejects | · |
| Movement and indexing | bitcast | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | rejects | ✓ | · | rejects | rejects | · |
| Movement and indexing | bitcast | TF32 | ✓ | |||||||||||
| Logic, bits and integers | logicalNot | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalNot | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalNot | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalNot | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalNot | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalNot | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalNot | TF32 | ✓ | |||||||||||
| Logic, bits and integers | logicalAnd | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalAnd | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalAnd | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalAnd | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalAnd | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalAnd | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalAnd | TF32 | ✓ | |||||||||||
| Logic, bits and integers | logicalOr | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalOr | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalOr | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalOr | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Logic, bits and integers | logicalOr | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalOr | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalOr | TF32 | ✓ | |||||||||||
| Logic, bits and integers | logicalXor | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
| Logic, bits and integers | logicalXor | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
| Logic, bits and integers | logicalXor | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
| Logic, bits and integers | logicalXor | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
| Logic, bits and integers | logicalXor | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalXor | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · |
| Logic, bits and integers | logicalXor | TF32 | ✓ | |||||||||||
| Logic, bits and integers | bitwiseAnd | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseAnd | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseAnd | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseAnd | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseAnd | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseAnd | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseAnd | TF32 | ✓ | |||||||||||
| Logic, bits and integers | bitwiseOr | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseOr | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseOr | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseOr | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseOr | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseOr | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseOr | TF32 | ✓ | |||||||||||
| Logic, bits and integers | bitwiseXor | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseXor | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseXor | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseXor | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseXor | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseXor | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseXor | TF32 | ✓ | |||||||||||
| Logic, bits and integers | bitwiseNot | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseNot | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseNot | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseNot | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseNot | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseNot | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseNot | TF32 | ✓ | |||||||||||
| Logic, bits and integers | bitwiseLeftShift | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseLeftShift | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseLeftShift | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseLeftShift | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | bitwiseLeftShift | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseLeftShift | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | bitwiseLeftShift | TF32 | ✓ | |||||||||||
| Logic, bits and integers | shiftRightArith | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ |
| Logic, bits and integers | shiftRightArith | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ |
| Logic, bits and integers | shiftRightArith | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ |
| Logic, bits and integers | shiftRightArith | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | ✓ |
| Logic, bits and integers | shiftRightArith | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | · |
| Logic, bits and integers | shiftRightArith | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | · |
| Logic, bits and integers | shiftRightArith | TF32 | ✓ | |||||||||||
| Logic, bits and integers | shiftRightLogical | float64 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | shiftRightLogical | float32 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | shiftRightLogical | bfloat16 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | shiftRightLogical | float16 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | ✓ | ✓ | rejects | ✓ |
| Logic, bits and integers | shiftRightLogical | float8 E5M2 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | shiftRightLogical | float8 E4M3 | ✓ | ✓ | ✓ | ✓ | ✓ | 0 | ✓ | ✓ | · | ✓ | rejects | · |
| Logic, bits and integers | shiftRightLogical | TF32 | ✓ | |||||||||||
| Logic, bits and integers | populationCount | float64 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · |
| Logic, bits and integers | populationCount | float32 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · |
| Logic, bits and integers | populationCount | bfloat16 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · |
| Logic, bits and integers | populationCount | float16 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · |
| Logic, bits and integers | populationCount | float8 E5M2 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | · |
| Logic, bits and integers | populationCount | float8 E4M3 | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | · | · |
| Logic, bits and integers | populationCount | TF32 | ✓ | |||||||||||
| Logic, bits and integers | countLeadZeros | float64 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | float32 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | bfloat16 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | float16 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | float8 E5M2 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | float8 E4M3 | ✓ | · | · | ✓ | ✓ | · | · | · | · | · | · | · |
| Logic, bits and integers | countLeadZeros | TF32 | ✓ | |||||||||||
| Logic, bits and integers | mulhi | float64 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | float32 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | bfloat16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | float16 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | float8 E5M2 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | float8 E4M3 | ✓ | · | · | · | · | · | · | · | · | · | · | · |
| Logic, bits and integers | mulhi | TF32 | ✓ | |||||||||||
| Random | randUniform | float64 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randUniform | float32 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randUniform | bfloat16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randUniform | float16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randUniform | float8 E5M2 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | randUniform | float8 E4M3 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | randUniform | TF32 | rand | |||||||||||
| Random | randn | float64 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randn | float32 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randn | bfloat16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randn | float16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | randn | float8 E5M2 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | randn | float8 E4M3 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | randn | TF32 | rand | |||||||||||
| Random | bernoulliMask | float64 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | bernoulliMask | float32 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | bernoulliMask | bfloat16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | bernoulliMask | float16 | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand | rand |
| Random | bernoulliMask | float8 E5M2 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | bernoulliMask | float8 E4M3 | rand | rand | rand | rand | rand | rand | rand | rand | · | rand | rand | · |
| Random | bernoulliMask | TF32 | rand |
Start with basic arithmetic. PyTorch's CPU square root was one ULP away from the correctly rounded result for 2,490 of 400,089 float64 inputs, including \(\sqrt{2}\); on the A100, it matched the reference in every tested case. JAX and TensorFlow also had float32 mismatches on the A100, while NumPy, ONNX Runtime, and MLX matched the tested reference for these operations. IEEE 754 specifies correctly rounded results for basic arithmetic such as division and square root in its standard binary formats. We also found failures near zero. Some tested JAX CPU, TensorFlow, and CuPy paths flushed float32 subnormal values (very small representable numbers) to zero; JAX and TensorFlow did so in CPU float64 as well. The format could store the values, but those computations discarded them. At the opposite end of the range, the E4M3FN cast in PyTorch saturated where TorchLean's specified rounding produced NaN.
Normalization gives another example. Standardization subtracts a mean and divides by a standard deviation. With \(\mu\) the mean of \(n\) values, these two variances are equal over the reals:
\[ \begin{aligned} v&=\frac{1}{n}\sum_i x_i^2-\mu^2\\[3pt] &=\frac{1}{n}\sum_i(x_i-\mu)^2. \end{aligned} \]
The first formula subtracts two large, nearly equal numbers. When the inputs share a large mean, rounding can erase the small variance we wanted to measure. For the float32 row \([10001,10002,10003,10004]\), the default jax.nn.standardize computation gave zero variance instead of 1.25. Its first normalized value was about \(-474.34\) rather than \(-1.342\) on both devices. The JAX documentation actually warns about this and provides algorithm="stable". PyTorch Geometric's variance aggregation showed a similar problem: \([4095,4097,4097]\) gave \(-2\) in float32 where the true variance was \(8/9\), and the subsequent standard deviation returned zero.
Now look at matrix multiplication. A matrix multiplication is a collection of dot products, and the internal precision matters just as much as the type of the output. On the A100, TensorFlow and ONNX Runtime CUDA used TF32 for float32 matrix products in the tested default paths. TF32 retains 10 fraction bits (see NVIDIA's accuracy notes), so an input of 4097 is rounded to 4096:
\[ \begin{aligned} s_{\mathbb R}&=4097-4096+1=2,\\ s_{\mathrm{TF32}}&=4096-4096+1=1. \end{aligned} \]
Disabling TF32 gave the correctly rounded result in both libraries for this example. I'd like that setting to be much easier to see. A float32 output doesn't tell us what precision the library used for the products inside it.
Let's look at an activation example. Sigmoid always has a small positive value for a finite negative input, but ONNX Runtime returned zero at \(-16.1\) in float32 on the CPU, at \(-16.6\) on the A100, and at \(-36.8\) in float64, even though the answers were representable. The tanh approximation to GELU has a related cancellation problem. Writing it as \(G(x)\):
\[ \begin{aligned} z&=\sqrt{2/\pi}\,(x+0.044715x^3),\\[3pt] G(x)&=\tfrac12 x(1+\tanh z). \end{aligned} \]
For sufficiently negative \(x\), \(\tanh z\) rounds to \(-1\), so \(1+\tanh z\) becomes zero. At \(x=-6\) in float32, PyTorch, the tested Transformers variants, JAX, and TorchLean's usual tanh GELU returned negative zero instead of about \(-8.4\times10^{-11}\). Writing the same approximation with sigmoid \(\sigma\) keeps the small value. This is an algebraic rearrangement of the tanh formula, not a switch to the erf definition:
\[ \tfrac12 x(1+\tanh z)=x\,\sigma(2z). \]
Case study I: softmax and cross-entropy¶
A classifier produces scores, or logits, and softmax turns them into probabilities:
\[ p_i=\frac{e^{z_i}}{\sum_j e^{z_j}}. \]
For the correct class \(t\), the cross-entropy loss and its gradient over the real numbers are:
\[ \begin{aligned} L&=-\log p_t,\\[3pt] \frac{\partial L}{\partial z_t}&=p_t-1. \end{aligned} \]
For finite logits and more than one class, the target gradient should be negative, even if it is very small. Take logits \([9,-9,-9]\), with class 0 as the target. The usual trick of subtracting the largest logit prevents overflow but still leaves this denominator:
\[ \begin{aligned} D&=1+e^{-18}+e^{-18},\\ e^{-18}&\approx1.52\times10^{-8}. \end{aligned} \]
Each small exponential is less than half the float32 spacing above 1, so adding it to 1 rounds it away. The computed target probability becomes exactly 1, and both the loss and its target gradient become zero. But the true loss is positive and the gradient negative, each with magnitude about \(3.046\times10^{-8}\). Float32 can represent these numbers; we lost them in the addition to 1. This is the Softmax Collapse phenomenon that drew me into the project. The recent softmax rewrite gives a way around it.
The repair relies on two standard numerical functions. expm1(x) computes \(e^x-1\) without first rounding \(e^x\) to 1, and log1p(x) computes \(\log(1+x)\) without losing a small \(x\) in the addition. For instance, \(e^{10^{-8}}-1\) evaluates to zero if we compute it directly in float32, while expm1 keeps a value close to \(10^{-8}\). Rather than adding the small exponentials to 1, we save their sum as \(T\) and compute:
\[ \begin{aligned} T&=e^{-18}+e^{-18},\\ L&=\operatorname{log1p}(T),\\ g_0&=\operatorname{expm1}(-L). \end{aligned} \]
For this input, the rewritten float32 target gradient is correctly rounded. In the trace below, watch the step that adds the exponentials.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41100000 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc1100000 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc1100000 | −9 | −9 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1900000 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc1900000 | −18 | −18 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f800000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3282d314 | 1.5229979e−8 | 1.522998e−8 | 0.39 units in the last place |
| e₂ = exp(y2) | 0x3282d314 | 1.5229979e−8 | 1.522998e−8 | 0.39 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f800000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f800000 | 1 | 1 | 0.13 units in the last place |
| s₂ = s1 + e2 | 0x3f800000 | 1 | 1 | 0.26 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x00000000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x00000000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
| loss = −log p0 | 0x80000000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f800000 | 1 | 0.99999997 | 0.51 units in the last place |
| g₀ = p0 − 1 | 0x00000000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 5.81e−14. This lane is off by 3.05e−8, outside the bound.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41100000 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc1100000 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc1100000 | −9 | −9 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1900000 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc1900000 | −18 | −18 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3282d314 | 1.5229979e−8 | 1.522998e−8 | 0.39 units in the last place |
| e₂ = exp(y2) | 0x3282d314 | 1.5229979e−8 | 1.522998e−8 | 0.39 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3282d314 | 1.5229979e−8 | 1.522998e−8 | 0.39 units in the last place |
| t₂ = t1 + e2 | 0x3302d314 | 3.0459958e−8 | 3.0459959e−8 | 0.39 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3302d314 | 3.0459958e−8 | 3.0459959e−8 | 0.26 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb302d314 | −3.0459958e−8 | −3.0459959e−8 | 0.26 units in the last place |
| loss = −log p0 | 0x3302d314 | 3.0459958e−8 | 3.0459959e−8 | 0.26 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xb302d314 | −3.0459958e−8 | −3.0459959e−8 | 0.13 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xb302d314 | −3.0459958e−8 | −3.0459959e−8 | 0.13 units in the last place |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 5.81e−14. This lane is off by 4.5e−16, inside the bound.
The two small exponentials add up to 3.05e−8, less than half a unit of binary32 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −3.046e−8. TorchLean's is −3.046e−8, relative error 1.5e−8.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4110 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc110 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc110 | −9 | −9 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc190 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc190 | −18 | −18 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f80 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3283 | 1.5250407e−8 | 1.522998e−8 | 0.18 units in the last place |
| e₂ = exp(y2) | 0x3283 | 1.5250407e−8 | 1.522998e−8 | 0.18 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f80 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f80 | 1 | 1 | 1.5e−8 relative |
| s₂ = s1 + e2 | 0x3f80 | 1 | 1 | 3e−8 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f80 | 1 | 0.99999997 | 3e−8 relative |
| g₀ = p0 − 1 | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 3.81e−9 here, computed in Python; no theorem covers this input and format. This lane is off by 3.05e−8, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4110 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc110 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc110 | −9 | −9 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc190 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc190 | −18 | −18 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3283 | 1.5250407e−8 | 1.522998e−8 | 0.18 units in the last place |
| e₂ = exp(y2) | 0x3283 | 1.5250407e−8 | 1.522998e−8 | 0.18 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3283 | 1.5250407e−8 | 1.522998e−8 | 0.18 units in the last place |
| t₂ = t1 + e2 | 0x3303 | 3.0500814e−8 | 3.0459959e−8 | 0.18 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3303 | 3.0500814e−8 | 3.0459959e−8 | 0.18 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb303 | −3.0500814e−8 | −3.0459959e−8 | 0.18 units in the last place |
| loss = −log p0 | 0x3303 | 3.0500814e−8 | 3.0459959e−8 | 0.18 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xb303 | −3.0500814e−8 | −3.0459959e−8 | 0.18 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xb303 | −3.0500814e−8 | −3.0459959e−8 | 0.18 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 3.81e−9 here, computed in Python; no theorem covers this input and format. This lane is off by 4.09e−11, inside it.
The two small exponentials add up to 3.05e−8, less than half a unit of bfloat16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −3.046e−8. TorchLean's is −3.0501e−8, relative error 0.0013.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4880 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc880 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc880 | −9 | −9 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xcc80 | −18 | −18 | exact |
| y₂ = x2 − max | 0xcc80 | −18 | −18 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3c00 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x0000 | 0 | 1.522998e−8 | 0 where the exact value is not |
| e₂ = exp(y2) | 0x0000 | 0 | 1.522998e−8 | 0 where the exact value is not |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3c00 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3c00 | 1 | 1 | 1.5e−8 relative |
| s₂ = s1 + e2 | 0x3c00 | 1 | 1 | 3e−8 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3c00 | 1 | 0.99999997 | 3e−8 relative |
| g₀ = p0 − 1 | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 9.54e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 3.05e−8, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4880 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc880 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc880 | −9 | −9 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xcc80 | −18 | −18 | exact |
| y₂ = x2 − max | 0xcc80 | −18 | −18 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x0000 | 0 | 1.522998e−8 | 0 where the exact value is not |
| e₂ = exp(y2) | 0x0000 | 0 | 1.522998e−8 | 0 where the exact value is not |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x0000 | 0 | 1.522998e−8 | 0 where the exact value is not |
| t₂ = t1 + e2 | 0x0000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x0000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 3.0459959e−8 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0x0000 | 0 | −3.0459959e−8 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 9.54e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 3.05e−8, inside it.
The two small exponentials add up to 3.05e−8, less than half a unit of binary16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −3.046e−8. TorchLean's is 0 as well: exp of the gap, 1.52e−8, is less than half the smallest positive binary16 number (5.96e−8), so each exponential rounds to 0 before the sum. The correctly rounded gradient in binary16 is −5.96e−8.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4022000000000000 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc022000000000000 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc022000000000000 | −9 | −9 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc032000000000000 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc032000000000000 | −18 | −18 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3ff0000000000000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3e505a628c699fa1 | 1.522998e−8 | 1.522998e−8 | 0.22 units in the last place |
| e₂ = exp(y2) | 0x3e505a628c699fa1 | 1.522998e−8 | 1.522998e−8 | 0.22 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3ff0000000000000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3ff00000041698a3 | 1 | 1 | 0.1 units in the last place |
| s₂ = s1 + e2 | 0x3ff00000082d3146 | 1 | 1 | 0.21 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3e605a6287d24f16 | 3.0459959e−8 | 3.0459959e−8 | 6.9e6 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbe605a6287d24f16 | −3.0459959e−8 | −3.0459959e−8 | 6.9e6 units in the last place |
| loss = −log p0 | 0x3e605a6287d24f16 | 3.0459959e−8 | 3.0459959e−8 | 6.9e6 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3fefffffefa59d7c | 0.99999997 | 0.99999997 | 0.056 units in the last place |
| g₀ = p0 − 1 | 0xbe605a6284000000 | −3.0459959e−8 | −3.0459959e−8 | 9.3e5 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.08e−22 here, computed in Python; no theorem covers this input and format. This lane is off by 6.18e−18, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4022000000000000 | 9 | 9 | exact |
| x₁ = logit 1 | 0xc022000000000000 | −9 | −9 | exact |
| x₂ = logit 2 | 0xc022000000000000 | −9 | −9 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc032000000000000 | −18 | −18 | exact |
| y₂ = x2 − max | 0xc032000000000000 | −18 | −18 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3e505a628c699fa1 | 1.522998e−8 | 1.522998e−8 | 0.22 units in the last place |
| e₂ = exp(y2) | 0x3e505a628c699fa1 | 1.522998e−8 | 1.522998e−8 | 0.22 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3e505a628c699fa1 | 1.522998e−8 | 1.522998e−8 | 0.22 units in the last place |
| t₂ = t1 + e2 | 0x3e605a628c699fa1 | 3.0459959e−8 | 3.0459959e−8 | 0.22 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3e605a62883beeb6 | 3.0459959e−8 | 3.0459959e−8 | 0.24 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbe605a62883beeb6 | −3.0459959e−8 | −3.0459959e−8 | 0.24 units in the last place |
| loss = −log p0 | 0x3e605a62883beeb6 | 3.0459959e−8 | 3.0459959e−8 | 0.24 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbe605a62840e3dcd | −3.0459959e−8 | −3.0459959e−8 | 0.12 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbe605a62840e3dcd | −3.0459959e−8 | −3.0459959e−8 | 0.12 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.08e−22 here, computed in Python; no theorem covers this input and format. This lane is off by 7.98e−25, inside it.
The standard target gradient is −3.046e−8, relative error 2e−10. TorchLean's is −3.046e−8, relative error 2.6e−17.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x40800000 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc0800000 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc0800000 | −4 | −4 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1000000 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc1000000 | −8 | −8 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f800000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x39afe108 | 3.3546262e−4 | 3.3546263e−4 | 0.13 units in the last place |
| e₂ = exp(y2) | 0x39afe108 | 3.3546262e−4 | 3.3546263e−4 | 0.13 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f800000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f800afe | 1.0003355 | 1.0003355 | 0.064 units in the last place |
| s₂ = s1 + e2 | 0x3f8015fc | 1.0006709 | 1.0006709 | 0.13 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3a2fd0e7 | 6.7068491e−4 | 6.7070029e−4 | 260 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xba2fd0e7 | −6.7068491e−4 | −6.7070029e−4 | 260 units in the last place |
| loss = −log p0 | 0x3a2fd0e7 | 6.7068491e−4 | 6.7070029e−4 | 260 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f7fd410 | 0.99932957 | 0.99932952 | 0.71 units in the last place |
| g₀ = p0 − 1 | 0xba2fc000 | −6.7043304e−4 | −6.7047542e−4 | 730 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.28e−9 here, computed in Python; no theorem covers this input and format. This lane is off by 4.24e−8, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x40800000 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc0800000 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc0800000 | −4 | −4 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1000000 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc1000000 | −8 | −8 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x39afe108 | 3.3546262e−4 | 3.3546263e−4 | 0.13 units in the last place |
| e₂ = exp(y2) | 0x39afe108 | 3.3546262e−4 | 3.3546263e−4 | 0.13 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x39afe108 | 3.3546262e−4 | 3.3546263e−4 | 0.13 units in the last place |
| t₂ = t1 + e2 | 0x3a2fe108 | 6.7092525e−4 | 6.7092526e−4 | 0.13 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3a2fd1ef | 6.7070028e−4 | 6.7070029e−4 | 0.18 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xba2fd1ef | −6.7070028e−4 | −6.7070029e−4 | 0.18 units in the last place |
| loss = −log p0 | 0x3a2fd1ef | 6.7070028e−4 | 6.7070029e−4 | 0.18 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xba2fc2d8 | −6.7047542e−4 | −6.7047542e−4 | 0.046 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xba2fc2d8 | −6.7047542e−4 | −6.7047542e−4 | 0.046 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.28e−9 here, computed in Python; no theorem covers this input and format. This lane is off by 2.7e−12, inside it.
The standard target gradient is −6.7043e−4, relative error 6.3e−5. TorchLean's is −6.7048e−4, relative error 4e−9.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4080 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc080 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc080 | −4 | −4 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc100 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc100 | −8 | −8 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f80 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x39b0 | 3.3569336e−4 | 3.3546263e−4 | 0.12 units in the last place |
| e₂ = exp(y2) | 0x39b0 | 3.3569336e−4 | 3.3546263e−4 | 0.12 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f80 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f80 | 1 | 1.0003355 | 0.043 units in the last place |
| s₂ = s1 + e2 | 0x3f80 | 1 | 1.0006709 | 0.086 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 6.7070029e−4 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −6.7070029e−4 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 6.7070029e−4 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f80 | 1 | 0.99932952 | 0.17 units in the last place |
| g₀ = p0 − 1 | 0x0000 | 0 | −6.7047542e−4 | 0 where the exact value is not |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 8.38e−5. This lane is off by 6.7e−4, outside the bound.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4080 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc080 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc080 | −4 | −4 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc100 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc100 | −8 | −8 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x39b0 | 3.3569336e−4 | 3.3546263e−4 | 0.12 units in the last place |
| e₂ = exp(y2) | 0x39b0 | 3.3569336e−4 | 3.3546263e−4 | 0.12 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x39b0 | 3.3569336e−4 | 3.3546263e−4 | 0.12 units in the last place |
| t₂ = t1 + e2 | 0x3a30 | 6.7138672e−4 | 6.7092526e−4 | 0.12 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3a30 | 6.7138672e−4 | 6.7070029e−4 | 0.18 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xba30 | −6.7138672e−4 | −6.7070029e−4 | 0.18 units in the last place |
| loss = −log p0 | 0x3a30 | 6.7138672e−4 | 6.7070029e−4 | 0.18 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xba30 | −6.7138672e−4 | −6.7047542e−4 | 0.24 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xba30 | −6.7138672e−4 | −6.7047542e−4 | 0.24 units in the last place |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 8.38e−5. This lane is off by 9.11e−7, inside the bound.
The two small exponentials add up to 6.71e−4, less than half a unit of bfloat16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.705e−4. TorchLean's is −6.7139e−4, relative error 0.0014.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4400 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc400 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc400 | −4 | −4 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc800 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc800 | −8 | −8 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3c00 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x0d7f | 3.3545494e−4 | 3.3546263e−4 | 0.032 units in the last place |
| e₂ = exp(y2) | 0x0d7f | 3.3545494e−4 | 3.3546263e−4 | 0.032 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3c00 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3c00 | 1 | 1.0003355 | 0.34 units in the last place |
| s₂ = s1 + e2 | 0x3c00 | 1 | 1.0006709 | 0.69 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 6.7070029e−4 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −6.7070029e−4 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 6.7070029e−4 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3c00 | 1 | 0.99932952 | 1.4 units in the last place |
| g₀ = p0 − 1 | 0x0000 | 0 | −6.7047542e−4 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 1.14e−5 here, computed in Python; no theorem covers this input and format. This lane is off by 6.7e−4, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4400 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc400 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc400 | −4 | −4 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc800 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc800 | −8 | −8 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x0d7f | 3.3545494e−4 | 3.3546263e−4 | 0.032 units in the last place |
| e₂ = exp(y2) | 0x0d7f | 3.3545494e−4 | 3.3546263e−4 | 0.032 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x0d7f | 3.3545494e−4 | 3.3546263e−4 | 0.032 units in the last place |
| t₂ = t1 + e2 | 0x117f | 6.7090988e−4 | 6.7092526e−4 | 0.032 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x117f | 6.7090988e−4 | 6.7070029e−4 | 0.44 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x917f | −6.7090988e−4 | −6.7070029e−4 | 0.44 units in the last place |
| loss = −log p0 | 0x117f | 6.7090988e−4 | 6.7070029e−4 | 0.44 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0x917f | −6.7090988e−4 | −6.7047542e−4 | 0.91 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0x917f | −6.7090988e−4 | −6.7047542e−4 | 0.91 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.14e−5 here, computed in Python; no theorem covers this input and format. This lane is off by 4.34e−7, inside it.
The two small exponentials add up to 6.71e−4, less than half a unit of binary16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.705e−4. TorchLean's is −6.7091e−4, relative error 6.5e−4.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4010000000000000 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc010000000000000 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc010000000000000 | −4 | −4 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc020000000000000 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc020000000000000 | −8 | −8 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3ff0000000000000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3f35fc21041027ad | 3.3546263e−4 | 3.3546263e−4 | 0.27 units in the last place |
| e₂ = exp(y2) | 0x3f35fc21041027ad | 3.3546263e−4 | 3.3546263e−4 | 0.27 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3ff0000000000000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3ff0015fc2104102 | 1.0003355 | 1.0003355 | 0.48 units in the last place |
| s₂ = s1 + e2 | 0x3ff002bf84208204 | 1.0006709 | 1.0006709 | 0.96 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3f45fa3de5a56525 | 6.7070029e−4 | 6.7070029e−4 | 2000 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbf45fa3de5a56525 | −6.7070029e−4 | −6.7070029e−4 | 2000 units in the last place |
| loss = −log p0 | 0x3f45fa3de5a56525 | 6.7070029e−4 | 6.7070029e−4 | 2000 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3feffa81e9405ee0 | 0.99932952 | 0.99932952 | 1.7 units in the last place |
| g₀ = p0 − 1 | 0xbf45f85afe848000 | −6.7047542e−4 | −6.7047542e−4 | 1800 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 2.38e−18 here, computed in Python; no theorem covers this input and format. This lane is off by 1.9e−16, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4010000000000000 | 4 | 4 | exact |
| x₁ = logit 1 | 0xc010000000000000 | −4 | −4 | exact |
| x₂ = logit 2 | 0xc010000000000000 | −4 | −4 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc020000000000000 | −8 | −8 | exact |
| y₂ = x2 − max | 0xc020000000000000 | −8 | −8 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3f35fc21041027ad | 3.3546263e−4 | 3.3546263e−4 | 0.27 units in the last place |
| e₂ = exp(y2) | 0x3f35fc21041027ad | 3.3546263e−4 | 3.3546263e−4 | 0.27 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3f35fc21041027ad | 3.3546263e−4 | 3.3546263e−4 | 0.27 units in the last place |
| t₂ = t1 + e2 | 0x3f45fc21041027ad | 6.7092526e−4 | 6.7092526e−4 | 0.27 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3f45fa3de5a56cd0 | 6.7070029e−4 | 6.7070029e−4 | 0.2 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbf45fa3de5a56cd0 | −6.7070029e−4 | −6.7070029e−4 | 0.2 units in the last place |
| loss = −log p0 | 0x3f45fa3de5a56cd0 | 6.7070029e−4 | 6.7070029e−4 | 0.2 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbf45f85afe8486db | −6.7047542e−4 | −6.7047542e−4 | 0.38 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbf45f85afe8486db | −6.7047542e−4 | −6.7047542e−4 | 0.38 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 2.38e−18 here, computed in Python; no theorem covers this input and format. This lane is off by 4.14e−20, inside it.
The standard target gradient is −6.7048e−4, relative error 2.8e−13. TorchLean's is −6.7048e−4, relative error 6.2e−17.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41980000 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc1980000 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc1980000 | −19 | −19 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc2180000 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc2180000 | −38 | −38 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f800000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x2410c457 | 3.1391329e−17 | 3.1391328e−17 | 0.29 units in the last place |
| e₂ = exp(y2) | 0x2410c457 | 3.1391329e−17 | 3.1391328e−17 | 0.29 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f800000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f800000 | 1 | 1 | 3.1e−17 relative |
| s₂ = s1 + e2 | 0x3f800000 | 1 | 1 | 6.3e−17 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x00000000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x00000000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| loss = −log p0 | 0x80000000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f800000 | 1 | 1 | 6.3e−17 relative |
| g₀ = p0 − 1 | 0x00000000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 1.2e−22 here, computed in Python; no theorem covers this input and format. This lane is off by 6.28e−17, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41980000 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc1980000 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc1980000 | −19 | −19 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc2180000 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc2180000 | −38 | −38 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x2410c457 | 3.1391329e−17 | 3.1391328e−17 | 0.29 units in the last place |
| e₂ = exp(y2) | 0x2410c457 | 3.1391329e−17 | 3.1391328e−17 | 0.29 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x2410c457 | 3.1391329e−17 | 3.1391328e−17 | 0.29 units in the last place |
| t₂ = t1 + e2 | 0x2490c457 | 6.2782658e−17 | 6.2782656e−17 | 0.29 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x2490c457 | 6.2782658e−17 | 6.2782656e−17 | 0.29 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xa490c457 | −6.2782658e−17 | −6.2782656e−17 | 0.29 units in the last place |
| loss = −log p0 | 0x2490c457 | 6.2782658e−17 | 6.2782656e−17 | 0.29 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xa490c457 | −6.2782658e−17 | −6.2782656e−17 | 0.29 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xa490c457 | −6.2782658e−17 | −6.2782656e−17 | 0.29 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.2e−22 here, computed in Python; no theorem covers this input and format. This lane is off by 1.93e−24, inside it.
The two small exponentials add up to 6.28e−17, less than half a unit of binary32 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.278e−17. TorchLean's is −6.2783e−17, relative error 3.1e−8.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4198 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc198 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc198 | −19 | −19 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc218 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc218 | −38 | −38 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f80 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x2411 | 3.1441863e−17 | 3.1391328e−17 | 0.23 units in the last place |
| e₂ = exp(y2) | 0x2411 | 3.1441863e−17 | 3.1391328e−17 | 0.23 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f80 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f80 | 1 | 1 | 3.1e−17 relative |
| s₂ = s1 + e2 | 0x3f80 | 1 | 1 | 6.3e−17 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f80 | 1 | 1 | 6.3e−17 relative |
| g₀ = p0 − 1 | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 7.85e−18 here, computed in Python; no theorem covers this input and format. This lane is off by 6.28e−17, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4198 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc198 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc198 | −19 | −19 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc218 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc218 | −38 | −38 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x2411 | 3.1441863e−17 | 3.1391328e−17 | 0.23 units in the last place |
| e₂ = exp(y2) | 0x2411 | 3.1441863e−17 | 3.1391328e−17 | 0.23 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x2411 | 3.1441863e−17 | 3.1391328e−17 | 0.23 units in the last place |
| t₂ = t1 + e2 | 0x2491 | 6.2883726e−17 | 6.2782656e−17 | 0.23 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x2491 | 6.2883726e−17 | 6.2782656e−17 | 0.23 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xa491 | −6.2883726e−17 | −6.2782656e−17 | 0.23 units in the last place |
| loss = −log p0 | 0x2491 | 6.2883726e−17 | 6.2782656e−17 | 0.23 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xa491 | −6.2883726e−17 | −6.2782656e−17 | 0.23 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xa491 | −6.2883726e−17 | −6.2782656e−17 | 0.23 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 7.85e−18 here, computed in Python; no theorem covers this input and format. This lane is off by 1.01e−19, inside it.
The two small exponentials add up to 6.28e−17, less than half a unit of bfloat16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.278e−17. TorchLean's is −6.2884e−17, relative error 0.0016.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4cc0 | 19 | 19 | exact |
| x₁ = logit 1 | 0xccc0 | −19 | −19 | exact |
| x₂ = logit 2 | 0xccc0 | −19 | −19 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xd0c0 | −38 | −38 | exact |
| y₂ = x2 − max | 0xd0c0 | −38 | −38 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3c00 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x0000 | 0 | 3.1391328e−17 | 0 where the exact value is not |
| e₂ = exp(y2) | 0x0000 | 0 | 3.1391328e−17 | 0 where the exact value is not |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3c00 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3c00 | 1 | 1 | 3.1e−17 relative |
| s₂ = s1 + e2 | 0x3c00 | 1 | 1 | 6.3e−17 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3c00 | 1 | 1 | 6.3e−17 relative |
| g₀ = p0 − 1 | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 9.54e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 6.28e−17, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4cc0 | 19 | 19 | exact |
| x₁ = logit 1 | 0xccc0 | −19 | −19 | exact |
| x₂ = logit 2 | 0xccc0 | −19 | −19 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xd0c0 | −38 | −38 | exact |
| y₂ = x2 − max | 0xd0c0 | −38 | −38 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x0000 | 0 | 3.1391328e−17 | 0 where the exact value is not |
| e₂ = exp(y2) | 0x0000 | 0 | 3.1391328e−17 | 0 where the exact value is not |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x0000 | 0 | 3.1391328e−17 | 0 where the exact value is not |
| t₂ = t1 + e2 | 0x0000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x0000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0x0000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 9.54e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 6.28e−17, inside it.
The two small exponentials add up to 6.28e−17, less than half a unit of binary16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.278e−17. TorchLean's is 0 as well: exp of the gap, 3.14e−17, is less than half the smallest positive binary16 number (5.96e−8), so each exponential rounds to 0 before the sum. Here 0 is also the correctly rounded gradient.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4033000000000000 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc033000000000000 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc033000000000000 | −19 | −19 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc043000000000000 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc043000000000000 | −38 | −38 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3ff0000000000000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3c82188ad6ae3303 | 3.1391328e−17 | 3.1391328e−17 | 0.054 units in the last place |
| e₂ = exp(y2) | 0x3c82188ad6ae3303 | 3.1391328e−17 | 3.1391328e−17 | 0.054 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3ff0000000000000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3ff0000000000000 | 1 | 1 | 0.14 units in the last place |
| s₂ = s1 + e2 | 0x3ff0000000000000 | 1 | 1 | 0.28 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000000000000000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000000000000000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
| loss = −log p0 | 0x8000000000000000 | 0 | 6.2782656e−17 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3ff0000000000000 | 1 | 1 | 0.57 units in the last place |
| g₀ = p0 − 1 | 0x0000000000000000 | 0 | −6.2782656e−17 | 0 where the exact value is not |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 2.23e−31. This lane is off by 6.28e−17, outside the bound.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4033000000000000 | 19 | 19 | exact |
| x₁ = logit 1 | 0xc033000000000000 | −19 | −19 | exact |
| x₂ = logit 2 | 0xc033000000000000 | −19 | −19 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc043000000000000 | −38 | −38 | exact |
| y₂ = x2 − max | 0xc043000000000000 | −38 | −38 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3c82188ad6ae3303 | 3.1391328e−17 | 3.1391328e−17 | 0.054 units in the last place |
| e₂ = exp(y2) | 0x3c82188ad6ae3303 | 3.1391328e−17 | 3.1391328e−17 | 0.054 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3c82188ad6ae3303 | 3.1391328e−17 | 3.1391328e−17 | 0.054 units in the last place |
| t₂ = t1 + e2 | 0x3c92188ad6ae3303 | 6.2782656e−17 | 6.2782656e−17 | 0.054 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3c92188ad6ae3303 | 6.2782656e−17 | 6.2782656e−17 | 0.11 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbc92188ad6ae3303 | −6.2782656e−17 | −6.2782656e−17 | 0.11 units in the last place |
| loss = −log p0 | 0x3c92188ad6ae3303 | 6.2782656e−17 | 6.2782656e−17 | 0.11 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbc92188ad6ae3303 | −6.2782656e−17 | −6.2782656e−17 | 0.27 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbc92188ad6ae3303 | −6.2782656e−17 | −6.2782656e−17 | 0.27 units in the last place |
Lean's theorems check this gradient: |computed − exact| ≤ 32u·|exact| + 32η = 2.23e−31. This lane is off by 3.28e−33, inside the bound.
The two small exponentials add up to 6.28e−17, less than half a unit of binary64 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −6.278e−17. TorchLean's is −6.2783e−17, relative error 5.2e−17.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41a00000 | 20 | 20 | exact |
| x₁ = logit 1 | 0x41200000 | 10 | 10 | exact |
| x₂ = logit 2 | 0x00000000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1200000 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc1a00000 | −20 | −20 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f800000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x383e6bce | 4.5399931e−5 | 4.539993e−5 | 0.33 units in the last place |
| e₂ = exp(y2) | 0x310da433 | 2.0611537e−9 | 2.0611536e−9 | 0.31 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f800000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f80017d | 1.0000454 | 1.0000454 | 0.16 units in the last place |
| s₂ = s1 + e2 | 0x3f80017d | 1.0000454 | 1.0000454 | 0.14 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x383e7ee4 | 4.5417706e−5 | 4.540096e−5 | 4600 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb83e7ee4 | −4.5417706e−5 | −4.540096e−5 | 4600 units in the last place |
| loss = −log p0 | 0x383e7ee4 | 4.5417706e−5 | 4.540096e−5 | 4600 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f7ffd06 | 0.99995458 | 0.9999546 | 0.32 units in the last place |
| g₀ = p0 − 1 | 0xb83e8000 | −4.5418739e−5 | −4.539993e−5 | 5200 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 8.66e−11 here, computed in Python; no theorem covers this input and format. This lane is off by 1.88e−8, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41a00000 | 20 | 20 | exact |
| x₁ = logit 1 | 0x41200000 | 10 | 10 | exact |
| x₂ = logit 2 | 0x00000000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc1200000 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc1a00000 | −20 | −20 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x383e6bce | 4.5399931e−5 | 4.539993e−5 | 0.33 units in the last place |
| e₂ = exp(y2) | 0x310da433 | 2.0611537e−9 | 2.0611536e−9 | 0.31 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x383e6bce | 4.5399931e−5 | 4.539993e−5 | 0.33 units in the last place |
| t₂ = t1 + e2 | 0x383e6e05 | 4.5401994e−5 | 4.5401991e−5 | 0.77 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x383e6cea | 4.5400964e−5 | 4.540096e−5 | 1.1 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb83e6cea | −4.5400964e−5 | −4.540096e−5 | 1.1 units in the last place |
| loss = −log p0 | 0x383e6cea | 4.5400964e−5 | 4.540096e−5 | 1.1 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xb83e6bcf | −4.5399935e−5 | −4.539993e−5 | 1.4 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xb83e6bcf | −4.5399935e−5 | −4.539993e−5 | 1.4 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 8.66e−11 here, computed in Python; no theorem covers this input and format. This lane is off by 4.94e−12, inside it.
The standard target gradient is −4.5419e−5, relative error 4.1e−4. TorchLean's is −4.54e−5, relative error 1.1e−7.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41a0 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4120 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc120 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc1a0 | −20 | −20 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f80 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x383e | 4.529953e−5 | 4.539993e−5 | 0.42 units in the last place |
| e₂ = exp(y2) | 0x310e | 2.066372e−9 | 2.0611536e−9 | 0.36 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f80 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3f80 | 1 | 1.0000454 | 4.5e−5 relative |
| s₂ = s1 + e2 | 0x3f80 | 1 | 1.0000454 | 4.5e−5 relative |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 4.540096e−5 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −4.540096e−5 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 4.540096e−5 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f80 | 1 | 0.9999546 | 0.012 units in the last place |
| g₀ = p0 − 1 | 0x0000 | 0 | −4.539993e−5 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 5.67e−6 here, computed in Python; no theorem covers this input and format. This lane is off by 4.54e−5, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x41a0 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4120 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc120 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc1a0 | −20 | −20 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x383e | 4.529953e−5 | 4.539993e−5 | 0.42 units in the last place |
| e₂ = exp(y2) | 0x310e | 2.066372e−9 | 2.0611536e−9 | 0.36 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x383e | 4.529953e−5 | 4.539993e−5 | 0.42 units in the last place |
| t₂ = t1 + e2 | 0x383e | 4.529953e−5 | 4.5401991e−5 | 0.43 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x383e | 4.529953e−5 | 4.540096e−5 | 0.43 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb83e | −4.529953e−5 | −4.540096e−5 | 0.43 units in the last place |
| loss = −log p0 | 0x383e | 4.529953e−5 | 4.540096e−5 | 0.43 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xb83e | −4.529953e−5 | −4.539993e−5 | 0.42 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xb83e | −4.529953e−5 | −4.539993e−5 | 0.42 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 5.67e−6 here, computed in Python; no theorem covers this input and format. This lane is off by 1e−7, inside it.
The two small exponentials add up to 4.54e−5, less than half a unit of bfloat16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −4.54e−5. TorchLean's is −4.53e−5, relative error 0.0022.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4d00 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4900 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc900 | −10 | −10 | exact |
| y₂ = x2 − max | 0xcd00 | −20 | −20 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3c00 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x02fa | 4.5418739e−5 | 4.539993e−5 | 0.32 units in the last place |
| e₂ = exp(y2) | 0x0000 | 0 | 2.0611536e−9 | 0 where the exact value is not |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3c00 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3c00 | 1 | 1.0000454 | 0.046 units in the last place |
| s₂ = s1 + e2 | 0x3c00 | 1 | 1.0000454 | 0.046 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x0000 | 0 | 4.540096e−5 | 0 where the exact value is not |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x0000 | 0 | −4.540096e−5 | 0 where the exact value is not |
| loss = −log p0 | 0x8000 | 0 | 4.540096e−5 | 0 where the exact value is not |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3c00 | 1 | 0.9999546 | 0.093 units in the last place |
| g₀ = p0 − 1 | 0x0000 | 0 | −4.539993e−5 | 0 where the exact value is not |
The theorems' tolerance, 32u·|exact| + 32η, is 1.66e−6 here, computed in Python; no theorem covers this input and format. This lane is off by 4.54e−5, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4d00 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4900 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc900 | −10 | −10 | exact |
| y₂ = x2 − max | 0xcd00 | −20 | −20 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x02fa | 4.5418739e−5 | 4.539993e−5 | 0.32 units in the last place |
| e₂ = exp(y2) | 0x0000 | 0 | 2.0611536e−9 | 0 where the exact value is not |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x02fa | 4.5418739e−5 | 4.539993e−5 | 0.32 units in the last place |
| t₂ = t1 + e2 | 0x02fa | 4.5418739e−5 | 4.5401991e−5 | 0.28 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x02fa | 4.5418739e−5 | 4.540096e−5 | 0.3 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0x82fa | −4.5418739e−5 | −4.540096e−5 | 0.3 units in the last place |
| loss = −log p0 | 0x02fa | 4.5418739e−5 | 4.540096e−5 | 0.3 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0x82fa | −4.5418739e−5 | −4.539993e−5 | 0.32 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0x82fa | −4.5418739e−5 | −4.539993e−5 | 0.32 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.66e−6 here, computed in Python; no theorem covers this input and format. This lane is off by 1.88e−8, inside it.
The two small exponentials add up to 4.54e−5, less than half a unit of binary16 at 1, so the standard sum rounds to exactly 1. The standard target gradient is 0; the exact one is −4.54e−5. TorchLean's is −4.5419e−5, relative error 4.1e−4.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4034000000000000 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4024000000000000 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000000000000000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc024000000000000 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc034000000000000 | −20 | −20 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3ff0000000000000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3f07cd79b5647c9b | 4.539993e−5 | 4.539993e−5 | 0.39 units in the last place |
| e₂ = exp(y2) | 0x3e21b48655f37267 | 2.0611536e−9 | 2.0611536e−9 | 0.1 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3ff0000000000000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3ff0002f9af36ac9 | 1.0000454 | 1.0000454 | 0.027 units in the last place |
| s₂ = s1 + e2 | 0x3ff0002f9b810efc | 1.0000454 | 1.0000454 | 0.34 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3f07cd9d1de4dab1 | 4.540096e−5 | 4.540096e−5 | 11000 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbf07cd9d1de4dab1 | −4.540096e−5 | −4.540096e−5 | 11000 units in the last place |
| loss = −log p0 | 0x3f07cd9d1de4dab1 | 4.540096e−5 | 4.540096e−5 | 11000 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3fefffa0ca192db8 | 0.9999546 | 0.9999546 | 0.87 units in the last place |
| g₀ = p0 − 1 | 0xbf07cd79b4920000 | −4.539993e−5 | −4.539993e−5 | 14000 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.61e−19 here, computed in Python; no theorem covers this input and format. This lane is off by 9.71e−17, outside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4034000000000000 | 20 | 20 | exact |
| x₁ = logit 1 | 0x4024000000000000 | 10 | 10 | exact |
| x₂ = logit 2 | 0x0000000000000000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xc024000000000000 | −10 | −10 | exact |
| y₂ = x2 − max | 0xc034000000000000 | −20 | −20 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3f07cd79b5647c9b | 4.539993e−5 | 4.539993e−5 | 0.39 units in the last place |
| e₂ = exp(y2) | 0x3e21b48655f37267 | 2.0611536e−9 | 2.0611536e−9 | 0.1 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3f07cd79b5647c9b | 4.539993e−5 | 4.539993e−5 | 0.39 units in the last place |
| t₂ = t1 + e2 | 0x3f07cdc0877dd469 | 4.5401991e−5 | 4.5401991e−5 | 0.6 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3f07cd9d1de4af1b | 4.540096e−5 | 4.540096e−5 | 0.81 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbf07cd9d1de4af1b | −4.540096e−5 | −4.540096e−5 | 0.81 units in the last place |
| loss = −log p0 | 0x3f07cd9d1de4af1b | 4.540096e−5 | 4.540096e−5 | 0.81 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbf07cd79b491c808 | −4.539993e−5 | −4.539993e−5 | 0.53 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbf07cd79b491c808 | −4.539993e−5 | −4.539993e−5 | 0.53 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.61e−19 here, computed in Python; no theorem covers this input and format. This lane is off by 3.57e−21, inside it.
The standard target gradient is −4.54e−5, relative error 2.1e−12. TorchLean's is −4.54e−5, relative error 7.9e−17.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x40000000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3f800000 | 1 | 1 | exact |
| x₂ = logit 2 | 0x00000000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbf800000 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc0000000 | −2 | −2 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f800000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3ebc5ab2 | 0.36787945 | 0.36787944 | 0.31 units in the last place |
| e₂ = exp(y2) | 0x3e0a9555 | 0.13533528 | 0.13533528 | 0.12 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f800000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3faf16ac | 1.3678794 | 1.3678794 | 0.42 units in the last place |
| s₂ = s1 + e2 | 0x3fc06957 | 1.5032147 | 1.5032147 | 0.063 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3ed0b1ba | 0.40760595 | 0.40760596 | 0.62 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbed0b1ba | −0.40760595 | −0.40760596 | 0.62 units in the last place |
| loss = −log p0 | 0x3ed0b1ba | 0.40760595 | 0.40760596 | 0.62 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f2a4d3b | 0.66524094 | 0.66524096 | 0.21 units in the last place |
| g₀ = p0 − 1 | 0xbeab658a | −0.33475906 | −0.33475904 | 0.41 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 6.39e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 1.23e−8, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x40000000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3f800000 | 1 | 1 | exact |
| x₂ = logit 2 | 0x00000000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x00000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbf800000 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc0000000 | −2 | −2 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3ebc5ab2 | 0.36787945 | 0.36787944 | 0.31 units in the last place |
| e₂ = exp(y2) | 0x3e0a9555 | 0.13533528 | 0.13533528 | 0.12 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3ebc5ab2 | 0.36787945 | 0.36787944 | 0.31 units in the last place |
| t₂ = t1 + e2 | 0x3f00d2ae | 0.50321472 | 0.50321472 | 0.13 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3ed0b1ba | 0.40760595 | 0.40760596 | 0.62 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbed0b1ba | −0.40760595 | −0.40760596 | 0.62 units in the last place |
| loss = −log p0 | 0x3ed0b1ba | 0.40760595 | 0.40760596 | 0.62 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbeab6589 | −0.33475903 | −0.33475904 | 0.59 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbeab6589 | −0.33475903 | −0.33475904 | 0.59 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 6.39e−7 here, computed in Python; no theorem covers this input and format. This lane is off by 1.75e−8, inside it.
The standard target gradient is −0.33476, relative error 3.7e−8. TorchLean's is −0.33476, relative error 5.2e−8.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3f80 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbf80 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000 | −2 | −2 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3f80 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3ebc | 0.3671875 | 0.36787944 | 0.35 units in the last place |
| e₂ = exp(y2) | 0x3e0b | 0.13574219 | 0.13533528 | 0.42 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3f80 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3faf | 1.3671875 | 1.3678794 | 0.089 units in the last place |
| s₂ = s1 + e2 | 0x3fc0 | 1.5 | 1.5032147 | 0.41 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3ed0 | 0.40625 | 0.40760596 | 0.69 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbed0 | −0.40625 | −0.40760596 | 0.69 units in the last place |
| loss = −log p0 | 0x3ed0 | 0.40625 | 0.40760596 | 0.69 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3f2b | 0.66796875 | 0.66524096 | 0.7 units in the last place |
| g₀ = p0 − 1 | 0xbeaa | −0.33203125 | −0.33475904 | 1.4 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 0.0418 here, computed in Python; no theorem covers this input and format. This lane is off by 0.00273, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3f80 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbf80 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000 | −2 | −2 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3ebc | 0.3671875 | 0.36787944 | 0.35 units in the last place |
| e₂ = exp(y2) | 0x3e0b | 0.13574219 | 0.13533528 | 0.42 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3ebc | 0.3671875 | 0.36787944 | 0.35 units in the last place |
| t₂ = t1 + e2 | 0x3f01 | 0.50390625 | 0.50321472 | 0.18 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3ed1 | 0.40820313 | 0.40760596 | 0.31 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbed1 | −0.40820313 | −0.40760596 | 0.31 units in the last place |
| loss = −log p0 | 0x3ed1 | 0.40820313 | 0.40760596 | 0.31 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbeac | −0.3359375 | −0.33475904 | 0.6 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbeac | −0.3359375 | −0.33475904 | 0.6 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 0.0418 here, computed in Python; no theorem covers this input and format. This lane is off by 0.00118, inside it.
The standard target gradient is −0.33203, relative error 0.0081. TorchLean's is −0.33594, relative error 0.0035.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3c00 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbc00 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000 | −2 | −2 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3c00 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x35e3 | 0.36791992 | 0.36787944 | 0.17 units in the last place |
| e₂ = exp(y2) | 0x3055 | 0.13537598 | 0.13533528 | 0.33 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3c00 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3d79 | 1.3681641 | 1.3678794 | 0.29 units in the last place |
| s₂ = s1 + e2 | 0x3e04 | 1.5039063 | 1.5032147 | 0.71 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3687 | 0.40795898 | 0.40760596 | 1.4 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb687 | −0.40795898 | −0.40760596 | 1.4 units in the last place |
| loss = −log p0 | 0x3687 | 0.40795898 | 0.40760596 | 1.4 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3952 | 0.66503906 | 0.66524096 | 0.41 units in the last place |
| g₀ = p0 − 1 | 0xb55c | −0.33496094 | −0.33475904 | 0.83 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 0.00523 here, computed in Python; no theorem covers this input and format. This lane is off by 2.02e−4, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3c00 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbc00 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000 | −2 | −2 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x35e3 | 0.36791992 | 0.36787944 | 0.17 units in the last place |
| e₂ = exp(y2) | 0x3055 | 0.13537598 | 0.13533528 | 0.33 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x35e3 | 0.36791992 | 0.36787944 | 0.17 units in the last place |
| t₂ = t1 + e2 | 0x3807 | 0.50341797 | 0.50321472 | 0.42 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3686 | 0.40771484 | 0.40760596 | 0.45 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xb686 | −0.40771484 | −0.40760596 | 0.45 units in the last place |
| loss = −log p0 | 0x3686 | 0.40771484 | 0.40760596 | 0.45 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xb55b | −0.3347168 | −0.33475904 | 0.17 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xb55b | −0.3347168 | −0.33475904 | 0.17 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 0.00523 here, computed in Python; no theorem covers this input and format. This lane is off by 4.22e−5, inside it.
The standard target gradient is −0.33496, relative error 6e−4. TorchLean's is −0.33472, relative error 1.3e−4.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000000000000000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3ff0000000000000 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000000000000000 | 0 | 0 | exact |
x − max
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbff0000000000000 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000000000000000 | −2 | −2 | exact |
exp
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₀ = exp(y0) | 0x3ff0000000000000 | 1 | 1 | exact |
| e₁ = exp(y1) | 0x3fd78b56362cef38 | 0.36787944 | 0.36787944 | 0.22 units in the last place |
| e₂ = exp(y2) | 0x3fc152aaa3bf81cc | 0.13533528 | 0.13533528 | 0.38 units in the last place |
running sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| s₀ = 0 + e0 | 0x3ff0000000000000 | 1 | 1 | exact |
| s₁ = s0 + e1 | 0x3ff5e2d58d8b3bce | 1.3678794 | 1.3678794 | 0.056 units in the last place |
| s₂ = s1 + e2 | 0x3ff80d2ae2032c08 | 1.5032147 | 1.5032147 | 0.6 units in the last place |
log of the sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log s = log(s2) | 0x3fda163753bc5c9d | 0.40760596 | 0.40760596 | 1.9 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbfda163753bc5c9d | −0.40760596 | −0.40760596 | 1.9 units in the last place |
| loss = −log p0 | 0x3fda163753bc5c9d | 0.40760596 | 0.40760596 | 1.9 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| p₀ = e0 / s2 | 0x3fe549a766a06790 | 0.66524096 | 0.66524096 | 0.94 units in the last place |
| g₀ = p0 − 1 | 0xbfd56cb132bf30e0 | −0.33475904 | −0.33475904 | 1.9 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.19e−15 here, computed in Python; no theorem covers this input and format. This lane is off by 1.05e−16, inside it.
logits
| node | bits | computed | exact | error |
|---|---|---|---|---|
| x₀ = logit 0 | 0x4000000000000000 | 2 | 2 | exact |
| x₁ = logit 1 | 0x3ff0000000000000 | 1 | 1 | exact |
| x₂ = logit 2 | 0x0000000000000000 | 0 | 0 | exact |
x − x[pivot]
| node | bits | computed | exact | error |
|---|---|---|---|---|
| y₀ = x0 − max | 0x0000000000000000 | 0 | 0 | exact |
| y₁ = x1 − max | 0xbff0000000000000 | −1 | −1 | exact |
| y₂ = x2 − max | 0xc000000000000000 | −2 | −2 | exact |
exp, off the pivot
| node | bits | computed | exact | error |
|---|---|---|---|---|
| e₁ = exp(y1) | 0x3fd78b56362cef38 | 0.36787944 | 0.36787944 | 0.22 units in the last place |
| e₂ = exp(y2) | 0x3fc152aaa3bf81cc | 0.13533528 | 0.13533528 | 0.38 units in the last place |
tail sum
| node | bits | computed | exact | error |
|---|---|---|---|---|
| t₁ = 0 + 0 + e1 | 0x3fd78b56362cef38 | 0.36787944 | 0.36787944 | 0.22 units in the last place |
| t₂ = t1 + e2 | 0x3fe01a55c406580f | 0.50321472 | 0.50321472 | 0.21 units in the last place |
log1p of the tail
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log1p t = log1p(t2) | 0x3fda163753bc5c9b | 0.40760596 | 0.40760596 | 0.12 units in the last place |
log-prob, loss
| node | bits | computed | exact | error |
|---|---|---|---|---|
| log p₀ = y0 − log s | 0xbfda163753bc5c9b | −0.40760596 | −0.40760596 | 0.12 units in the last place |
| loss = −log p0 | 0x3fda163753bc5c9b | 0.40760596 | 0.40760596 | 0.12 units in the last place |
target gradient
| node | bits | computed | exact | error |
|---|---|---|---|---|
| expm1 = expm1(log p0) | 0xbfd56cb132bf30de | −0.33475904 | −0.33475904 | 0.12 units in the last place |
| g₀ = −expm1(log p0)·(−1) − p0·0 | 0xbfd56cb132bf30de | −0.33475904 | −0.33475904 | 0.12 units in the last place |
The theorems' tolerance, 32u·|exact| + 32η, is 1.19e−15 here, computed in Python; no theorem covers this input and format. This lane is off by 6.48e−18, inside it.
The standard target gradient is −0.33476, relative error 3.1e−16. TorchLean's is −0.33476, relative error 1.9e−17.
Arithmetic and reference values
Values were evaluated in Lean with FloatLib. References use mpmath at 256 bits. The per-step records include computed values, reference values, errors, and bit patterns.
Other failures in losses and updates¶
We then modeled fifteen more formulas in Lean and checked the corresponding calls in the libraries. Most CPU results reproduced the predicted failures; the exception was PyTorch's fused bfloat16 tanh GELU, which computes in float32. GPU behavior sometimes differed, so the figure below keeps the devices separate. One example is the KL estimator used in TRL's GRPO training code. If \(d\) is the difference between two log probabilities, the estimator is:
\[ \begin{aligned} k(d)&=e^d-d-1,\\ e^d&\approx1+d+\tfrac12d^2\quad\text{near zero}. \end{aligned} \]
Near zero, those subtractions are supposed to leave a small positive penalty. At \(d=2^{-12}\) in float32, the direct expression returned zero instead of roughly \(3.0\times10^{-8}\); expm1(d) - d kept the value. We also saw PyTorch's KL divergence between nearby normal distributions return zero in one test and a negative value in another. Diffusion noise schedules expose a similar problem. Their noise level uses \(\sqrt{1-\alpha}\), where \(\alpha\) is a product of schedule values. In our binary16 example, \(\alpha\) rounded to 1, so the computed noise level vanished instead of being about 0.0148. Accumulating the logarithms and using expm1 to recover the small difference avoided that failure.
Some failures come from intermediate overflow rather than cancellation. A binary16 label smoothed cross entropy overflowed its batch sum and returned infinity instead of 1875. Log sum exp over 151,936 zeros should be about 11.93, but summing that many ones overflowed in several tested implementations; accumulating in float32 fixes it. Soft margin loss at \(-12\) in binary16 returned an infinite loss and a NaN gradient. Small constants can be just as dangerous. In one float32 clamp, eps=1e-8 disappeared from the upper limit \(1-\mathrm{eps}\), which rounded to 1 and produced infinity later. TorchLean's safeDiv adds \(10^{-6}\) to the denominator, but safeDiv(1, 0) still overflows in binary16 and E5M2. Stable Baselines3's squashed Gaussian uses an epsilon that changes the mathematical function itself; we count that separately rather than calling it a rounding failure.
A finite loss does not necessarily mean the gradient is usable either. An ℓ₃ norm on binary16 entries of \(2^{-13}\) produced a NaN gradient instead of about 0.397, while focal loss with exponent \(1/2\) produced zero loss and a NaN gradient at a float32 logit of \(-20\). We also found updates that simply stopped changing the state: a bfloat16 moving average stayed at \(1/64\) for 5,000 steps because every update rounded away, and an xLSTM memory decay rounded to 1 instead of about 0.9526.
Matches modelDifferent resultMixed across calls or formatsNot tested
| Case and library calls | Input and format | Original formula (Lean) | CPU result | A100 result | Replacement (Lean) |
|---|---|---|---|---|---|
| Softmax Collapse | |||||
Softmax cross-entropy, PyTorchF.log_softmax, F.cross_entropy and its backward | [9, −9, −9] float32; [4, −4, −4] bfloat16; [19, −19, −19] float64 | 0 (log-probability, loss and target gradient) | Matches modelin all three formats | Mixed resultsfloat32 and float64 same; bfloat16 gives −11/214, the correctly rounded value | −2143429/246 in float32, −11/214 in bfloat16 |
Softmax cross-entropy, JAXjax.nn.log_softmax, optax's softmax_cross_entropy_with_integer_labels, jax.grad | [9, −9, −9] float32; [4, −4, −4] bfloat16; [19, −19, −19] float64 | 0 | Matches modelin all three formats | Matches modelin all three formats | −2143429/246 in float32, −11/214 in bfloat16 |
| One plus something small | |||||
tanh-GELU, float32F.gelu(approximate='tanh'), gelu_new, gelu_pytorch_tanh, jax.nn.gelu | x = −6, float32 | −0 | Matches modelall four | Matches modelall four | −3040709/255 |
tanh-GELU, bfloat16F.gelu(approximate='tanh'), gelu_new, gelu_pytorch_tanh, jax.nn.gelu | x = −4, bfloat16 | −0 | Mixed resultsgelu_new and jax.nn.gelu same; F.gelu and gelu_pytorch_tanh give −147/221 | Mixed resultsgelu_new same; F.gelu and gelu_pytorch_tanh give −147/221, jax.nn.gelu −75/220 | −149/221 |
GRPO's k3 KL penaltyTRL's GRPO line in PyTorch; the same expression under jax.jit | d = 2−12, float32; d = 2−6, bfloat16 | 0 | Matches model | Matches model | 2−25 in float32 |
KL divergence of two normalskl_divergence of two Normals; of two 1-d MultivariateNormals | N(0, 1) and N(2−13, 1); σ = 1 and 1 + 2−13, float32 | 0; −2−27 | Matches model | Matches model | 2−27; 2047/237 |
Clamped logittorch.special.logit(x, eps=1e-8), torch.logit | x = 1, float32 | +∞ | Matches model | Matches model | 4828871/218 |
DDPM noise leveldiffusers' DDPMScheduler.add_noise | t = 1, binary16 | 0 | Matches model | Matches model | 243/214 |
Focal loss, γ = ½torchvision's sigmoid_focal_loss and its backward | logit −20, target 0, float32 | loss 0, gradient NaN | Matches model | Matches model | gradient 10357061/266 |
Weibull survival functionTFP's Weibull(5, 1).survival_function, log_survival_function | x = 2, float32 | 0 and −∞ | Matches model | Not testedCPU build only | 1868901/267 and −32 |
Moving average of weightsget_ema_multi_avg_fn(0.999) | average 1/64, parameter 69/212, bfloat16 | 1/64 after every step | Matches modelfor 5,000 steps | Matches modelfor 5,000 steps | float32 average: 8389263/229 after one step |
xLSTM forget gatexlstm's mLSTM, parallel_stabilized_simple | running sum −64, log gate −199/212, bfloat16 | decay 1 | Matches model | Matches model | 61/64 |
| Overflow before the division | |||||
Label smoothingF.cross_entropy(label_smoothing=0.125) | 3 rows [0, −30000], binary16 | +∞ | Matches model | Matches model | 1875 |
Log-sum-exptorch.logsumexp, F.log_softmax, F.cross_entropy; jax.nn.logsumexp, jax.nn.log_softmax, optax | 151,936 zeros, binary16 | ±∞ | Matches modelPyTorch and JAX | Mixed resultstorch.logsumexp and JAX same; PyTorch's log_softmax and cross_entropy give ±1527/27 | ±1527/27, with the sum in float32 |
Soft-margin lossF.soft_margin_loss and its backward | x = −12, binary16; x = −100, float32 | loss +∞, gradient NaN | Matches model | Matches model | 12 and −1 in binary16 |
Backward of a 3-normtorch.linalg.vector_norm(ord=3) | four entries 2−13, binary16 | NaN | Matches model | Matches model | 407/1024 |
| Cancellation | |||||
VariancePyTorch Geometric's VarAggregation, StdAggregation | [4095, 4097, 4097], float32 | variance −2, standard deviation 0 | Matches model | Matches model | 14913081/224 |
| A documented epsilon | |||||
Squashed GaussianStable-Baselines3's TanhBijector.log_prob_correction | u = 10, float32 | −14486613/220 | Matches model | Matches model | −4879471/218 |
Arithmetic and reference values
The two Lean columns use the first format listed for each case. A matching library result is either bit-for-bit identical or reproduces the same zero, infinity, or NaN. The CPU runs used an x86-64 machine running PyTorch's AVX-512 kernels.
For the direct KL formula, the generated absolute error allowance is larger than the penalty we're trying to measure. That bound still allows zero, so it doesn't tell us whether the small penalty survives rounding.
Precision and range are different problems¶
There are two separate limits in a floating point format. The fraction bits determine the spacing between nearby values, while the exponent bits determine the range. More fraction bits cannot save an answer that underflows, and a wider exponent range will not fix cancellation near 1. This is why bfloat16, with roughly the range of float32 but much coarser spacing, behaves differently from float16, which has more fraction bits near 1 but a much narrower range.
| Format | Exponent bits | Fraction bits | Gap above 1 | Largest finite value | Smallest normal value |
|---|---|---|---|---|---|
| float64 | 11 | 52 | \(2.2\times10^{-16}\) | \(1.8\times10^{308}\) | \(2.2\times10^{-308}\) |
| float32 | 8 | 23 | \(1.2\times10^{-7}\) | \(3.4\times10^{38}\) | \(1.2\times10^{-38}\) |
| TF32 | 8 | 10 | \(9.8\times10^{-4}\) | \(3.4\times10^{38}\) | \(1.2\times10^{-38}\) |
| bfloat16 | 8 | 7 | \(7.8\times10^{-3}\) | \(3.4\times10^{38}\) | \(1.2\times10^{-38}\) |
| float16 | 5 | 10 | \(9.8\times10^{-4}\) | 65,504 | \(6.1\times10^{-5}\) |
| E5M2 | 5 | 2 | 0.25 | 57,344 | \(6.1\times10^{-5}\) |
| E4M3FN | 4 | 3 | 0.125 | 448 | 0.0156 |
With FloatLib, we compared four original formulas and their replacements across 526 formats: 520 choices of exponent and fraction widths, three more float8 layouts, and three posit formats. The sweep below uses the same inputs for the original and rewritten expressions, so you can see whether a zero comes from precision, range, or the particular formula.
The softmax example makes the distinction especially clear. When the exponent range is sufficient, the original target gradient stays zero through 24 fraction bits. At 25 fraction bits it becomes nonzero, but is still nearly twice the true value. The rewrite avoids that precision problem. In very narrow formats, however, even the rewritten expression can return zero when the exponentials themselves underflow. Binary16 is one such case. That is why we also added the underflow fallback described below.
e = 4, f = 1
With 1 fraction bit the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−2 = 0.25, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 0.00781, so it rounds to 0 before anything is added.
e = 4, f = 2
With 2 fraction bits the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−3 = 0.125, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 0.00391, so it rounds to 0 before anything is added.
e = 4, f = 3
e−18 = 1.52e−8 is less than half a unit at 1, 2−4 = 0.0625, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 0.00195, so it rounds to 0 before anything is added.
e = 4, f = 4
e−18 = 1.52e−8 is less than half a unit at 1, 2−5 = 0.0313, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 9.77e−4, so it rounds to 0 before anything is added.
e = 4, f = 5
e−18 = 1.52e−8 is less than half a unit at 1, 2−6 = 0.0156, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 4.88e−4, so it rounds to 0 before anything is added.
e = 4, f = 6
e−18 = 1.52e−8 is less than half a unit at 1, 2−7 = 0.00781, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 2.44e−4, so it rounds to 0 before anything is added.
e = 4, f = 7
e−18 = 1.52e−8 is less than half a unit at 1, 2−8 = 0.00391, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.22e−4, so it rounds to 0 before anything is added.
e = 4, f = 8
e−18 = 1.52e−8 is less than half a unit at 1, 2−9 = 0.00195, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 6.1e−5, so it rounds to 0 before anything is added.
e = 4, f = 9
e−18 = 1.52e−8 is less than half a unit at 1, 2−10 = 9.77e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 3.05e−5, so it rounds to 0 before anything is added.
e = 4, f = 10
e−18 = 1.52e−8 is less than half a unit at 1, 2−11 = 4.88e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.53e−5, so it rounds to 0 before anything is added.
e = 4, f = 11
e−18 = 1.52e−8 is less than half a unit at 1, 2−12 = 2.44e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 7.63e−6, so it rounds to 0 before anything is added.
e = 4, f = 12
e−18 = 1.52e−8 is less than half a unit at 1, 2−13 = 1.22e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 3.81e−6, so it rounds to 0 before anything is added.
e = 4, f = 13
e−18 = 1.52e−8 is less than half a unit at 1, 2−14 = 6.1e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.91e−6, so it rounds to 0 before anything is added.
e = 4, f = 14
e−18 = 1.52e−8 is less than half a unit at 1, 2−15 = 3.05e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 9.54e−7, so it rounds to 0 before anything is added.
e = 4, f = 15
e−18 = 1.52e−8 is less than half a unit at 1, 2−16 = 1.53e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 4.77e−7, so it rounds to 0 before anything is added.
e = 4, f = 16
e−18 = 1.52e−8 is less than half a unit at 1, 2−17 = 7.63e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 2.38e−7, so it rounds to 0 before anything is added.
e = 4, f = 17
e−18 = 1.52e−8 is less than half a unit at 1, 2−18 = 3.81e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.19e−7, so it rounds to 0 before anything is added.
e = 4, f = 18
e−18 = 1.52e−8 is less than half a unit at 1, 2−19 = 1.91e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 5.96e−8, so it rounds to 0 before anything is added.
e = 4, f = 19
e−18 = 1.52e−8 is less than half a unit at 1, 2−20 = 9.54e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is between half the smallest positive number and the smallest positive number, 2.98e−8, so it rounds up to 2.98e−8, about twice its value.
e = 4, f = 20
e−18 = 1.52e−8 is less than half a unit at 1, 2−21 = 4.77e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 0.0156, so it keeps only 1 significant bit.
e = 4, f = 21
e−18 = 1.52e−8 is less than half a unit at 1, 2−22 = 2.38e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 0.0156, so it keeps only 2 significant bits.
e = 4, f = 22
e−18 = 1.52e−8 is less than half a unit at 1, 2−23 = 1.19e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 0.0156, so it keeps only 3 significant bits.
e = 4, f = 23
e−18 = 1.52e−8 is less than half a unit at 1, 2−24 = 5.96e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 0.0156, so it keeps only 4 significant bits.
e = 4, f = 24
e−18 = 1.52e−8 is less than half a unit at 1, 2−25 = 2.98e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 0.0156, so it keeps only 5 significant bits.
e = 4, f = 25
e−18 = 1.52e−8 is more than half a unit at 1, 2−26 = 1.49e−8, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.49e−8, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 6 significant bits.
e = 4, f = 26
e−18 = 1.52e−8 is more than half a unit at 1, 2−27 = 7.45e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.45e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 7 significant bits.
e = 4, f = 27
e−18 = 1.52e−8 is more than half a unit at 1, 2−28 = 3.73e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.73e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 8 significant bits.
e = 4, f = 28
e−18 = 1.52e−8 is more than half a unit at 1, 2−29 = 1.86e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.86e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 9 significant bits.
e = 4, f = 29
e−18 = 1.52e−8 is more than half a unit at 1, 2−30 = 9.31e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.31e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 10 significant bits.
e = 4, f = 30
e−18 = 1.52e−8 is more than half a unit at 1, 2−31 = 4.66e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.66e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 11 significant bits.
e = 4, f = 31
e−18 = 1.52e−8 is more than half a unit at 1, 2−32 = 2.33e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.33e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 12 significant bits.
e = 4, f = 32
e−18 = 1.52e−8 is more than half a unit at 1, 2−33 = 1.16e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.16e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 13 significant bits.
e = 4, f = 33
e−18 = 1.52e−8 is more than half a unit at 1, 2−34 = 5.82e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.82e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 14 significant bits.
e = 4, f = 34
e−18 = 1.52e−8 is more than half a unit at 1, 2−35 = 2.91e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.91e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 15 significant bits.
e = 4, f = 35
e−18 = 1.52e−8 is more than half a unit at 1, 2−36 = 1.46e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.46e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 16 significant bits.
e = 4, f = 36
e−18 = 1.52e−8 is more than half a unit at 1, 2−37 = 7.28e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.28e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 17 significant bits.
e = 4, f = 37
e−18 = 1.52e−8 is more than half a unit at 1, 2−38 = 3.64e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.64e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 18 significant bits.
e = 4, f = 38
e−18 = 1.52e−8 is more than half a unit at 1, 2−39 = 1.82e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.82e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 19 significant bits.
e = 4, f = 39
e−18 = 1.52e−8 is more than half a unit at 1, 2−40 = 9.09e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.09e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 20 significant bits.
e = 4, f = 40
e−18 = 1.52e−8 is more than half a unit at 1, 2−41 = 4.55e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.55e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 21 significant bits.
e = 4, f = 41
e−18 = 1.52e−8 is more than half a unit at 1, 2−42 = 2.27e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.27e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 22 significant bits.
e = 4, f = 42
e−18 = 1.52e−8 is more than half a unit at 1, 2−43 = 1.14e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.14e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 23 significant bits.
e = 4, f = 43
e−18 = 1.52e−8 is more than half a unit at 1, 2−44 = 5.68e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.68e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 24 significant bits.
e = 4, f = 44
e−18 = 1.52e−8 is more than half a unit at 1, 2−45 = 2.84e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.84e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 25 significant bits.
e = 4, f = 45
e−18 = 1.52e−8 is more than half a unit at 1, 2−46 = 1.42e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.42e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 26 significant bits.
e = 4, f = 46
e−18 = 1.52e−8 is more than half a unit at 1, 2−47 = 7.11e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.11e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 27 significant bits.
e = 4, f = 47
e−18 = 1.52e−8 is more than half a unit at 1, 2−48 = 3.55e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.55e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 28 significant bits.
e = 4, f = 48
e−18 = 1.52e−8 is more than half a unit at 1, 2−49 = 1.78e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.78e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 29 significant bits.
e = 4, f = 49
e−18 = 1.52e−8 is more than half a unit at 1, 2−50 = 8.88e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 8.88e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 30 significant bits.
e = 4, f = 50
e−18 = 1.52e−8 is more than half a unit at 1, 2−51 = 4.44e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.44e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 31 significant bits.
e = 4, f = 51
e−18 = 1.52e−8 is more than half a unit at 1, 2−52 = 2.22e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.22e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 32 significant bits.
e = 4, f = 52
e−18 = 1.52e−8 is more than half a unit at 1, 2−53 = 1.11e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.11e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 0.0156, so it keeps only 33 significant bits.
e = 5, f = 1
With 1 fraction bit the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−2 = 0.25, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 3.05e−5, so it rounds to 0 before anything is added.
e = 5, f = 2, E5M2
With 2 fraction bits the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−3 = 0.125, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.53e−5, so it rounds to 0 before anything is added.
e = 5, f = 3
e−18 = 1.52e−8 is less than half a unit at 1, 2−4 = 0.0625, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 7.63e−6, so it rounds to 0 before anything is added.
e = 5, f = 4
e−18 = 1.52e−8 is less than half a unit at 1, 2−5 = 0.0313, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 3.81e−6, so it rounds to 0 before anything is added.
e = 5, f = 5
e−18 = 1.52e−8 is less than half a unit at 1, 2−6 = 0.0156, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.91e−6, so it rounds to 0 before anything is added.
e = 5, f = 6
e−18 = 1.52e−8 is less than half a unit at 1, 2−7 = 0.00781, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 9.54e−7, so it rounds to 0 before anything is added.
e = 5, f = 7
e−18 = 1.52e−8 is less than half a unit at 1, 2−8 = 0.00391, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 4.77e−7, so it rounds to 0 before anything is added.
e = 5, f = 8
e−18 = 1.52e−8 is less than half a unit at 1, 2−9 = 0.00195, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 2.38e−7, so it rounds to 0 before anything is added.
e = 5, f = 9
e−18 = 1.52e−8 is less than half a unit at 1, 2−10 = 9.77e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 1.19e−7, so it rounds to 0 before anything is added.
e = 5, f = 10, binary16
e−18 = 1.52e−8 is less than half a unit at 1, 2−11 = 4.88e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is less than half the smallest positive number, 5.96e−8, so it rounds to 0 before anything is added.
e = 5, f = 11
e−18 = 1.52e−8 is less than half a unit at 1, 2−12 = 2.44e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is between half the smallest positive number and the smallest positive number, 2.98e−8, so it rounds up to 2.98e−8, about twice its value.
e = 5, f = 12
e−18 = 1.52e−8 is less than half a unit at 1, 2−13 = 1.22e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 1 significant bit.
e = 5, f = 13
e−18 = 1.52e−8 is less than half a unit at 1, 2−14 = 6.1e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 2 significant bits.
e = 5, f = 14
e−18 = 1.52e−8 is less than half a unit at 1, 2−15 = 3.05e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 3 significant bits.
e = 5, f = 15
e−18 = 1.52e−8 is less than half a unit at 1, 2−16 = 1.53e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 4 significant bits.
e = 5, f = 16
e−18 = 1.52e−8 is less than half a unit at 1, 2−17 = 7.63e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 5 significant bits.
e = 5, f = 17
e−18 = 1.52e−8 is less than half a unit at 1, 2−18 = 3.81e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 6 significant bits.
e = 5, f = 18
e−18 = 1.52e−8 is less than half a unit at 1, 2−19 = 1.91e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 7 significant bits.
e = 5, f = 19
e−18 = 1.52e−8 is less than half a unit at 1, 2−20 = 9.54e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 8 significant bits.
e = 5, f = 20
e−18 = 1.52e−8 is less than half a unit at 1, 2−21 = 4.77e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 9 significant bits.
e = 5, f = 21
e−18 = 1.52e−8 is less than half a unit at 1, 2−22 = 2.38e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 10 significant bits.
e = 5, f = 22
e−18 = 1.52e−8 is less than half a unit at 1, 2−23 = 1.19e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 11 significant bits.
e = 5, f = 23
e−18 = 1.52e−8 is less than half a unit at 1, 2−24 = 5.96e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 12 significant bits.
e = 5, f = 24
e−18 = 1.52e−8 is less than half a unit at 1, 2−25 = 2.98e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 13 significant bits.
e = 5, f = 25
e−18 = 1.52e−8 is more than half a unit at 1, 2−26 = 1.49e−8, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.49e−8, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 14 significant bits.
e = 5, f = 26
e−18 = 1.52e−8 is more than half a unit at 1, 2−27 = 7.45e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.45e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 15 significant bits.
e = 5, f = 27
e−18 = 1.52e−8 is more than half a unit at 1, 2−28 = 3.73e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.73e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 16 significant bits.
e = 5, f = 28
e−18 = 1.52e−8 is more than half a unit at 1, 2−29 = 1.86e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.86e−9, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 17 significant bits.
e = 5, f = 29
e−18 = 1.52e−8 is more than half a unit at 1, 2−30 = 9.31e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.31e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 18 significant bits.
e = 5, f = 30
e−18 = 1.52e−8 is more than half a unit at 1, 2−31 = 4.66e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.66e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 19 significant bits.
e = 5, f = 31
e−18 = 1.52e−8 is more than half a unit at 1, 2−32 = 2.33e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.33e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 20 significant bits.
e = 5, f = 32
e−18 = 1.52e−8 is more than half a unit at 1, 2−33 = 1.16e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.16e−10, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 21 significant bits.
e = 5, f = 33
e−18 = 1.52e−8 is more than half a unit at 1, 2−34 = 5.82e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.82e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 22 significant bits.
e = 5, f = 34
e−18 = 1.52e−8 is more than half a unit at 1, 2−35 = 2.91e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.91e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 23 significant bits.
e = 5, f = 35
e−18 = 1.52e−8 is more than half a unit at 1, 2−36 = 1.46e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.46e−11, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 24 significant bits.
e = 5, f = 36
e−18 = 1.52e−8 is more than half a unit at 1, 2−37 = 7.28e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.28e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 25 significant bits.
e = 5, f = 37
e−18 = 1.52e−8 is more than half a unit at 1, 2−38 = 3.64e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.64e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 26 significant bits.
e = 5, f = 38
e−18 = 1.52e−8 is more than half a unit at 1, 2−39 = 1.82e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.82e−12, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 27 significant bits.
e = 5, f = 39
e−18 = 1.52e−8 is more than half a unit at 1, 2−40 = 9.09e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.09e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 28 significant bits.
e = 5, f = 40
e−18 = 1.52e−8 is more than half a unit at 1, 2−41 = 4.55e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.55e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 29 significant bits.
e = 5, f = 41
e−18 = 1.52e−8 is more than half a unit at 1, 2−42 = 2.27e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.27e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 30 significant bits.
e = 5, f = 42
e−18 = 1.52e−8 is more than half a unit at 1, 2−43 = 1.14e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.14e−13, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 31 significant bits.
e = 5, f = 43
e−18 = 1.52e−8 is more than half a unit at 1, 2−44 = 5.68e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.68e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 32 significant bits.
e = 5, f = 44
e−18 = 1.52e−8 is more than half a unit at 1, 2−45 = 2.84e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.84e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 33 significant bits.
e = 5, f = 45
e−18 = 1.52e−8 is more than half a unit at 1, 2−46 = 1.42e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.42e−14, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 34 significant bits.
e = 5, f = 46
e−18 = 1.52e−8 is more than half a unit at 1, 2−47 = 7.11e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.11e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 35 significant bits.
e = 5, f = 47
e−18 = 1.52e−8 is more than half a unit at 1, 2−48 = 3.55e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.55e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 36 significant bits.
e = 5, f = 48
e−18 = 1.52e−8 is more than half a unit at 1, 2−49 = 1.78e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.78e−15, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 37 significant bits.
e = 5, f = 49
e−18 = 1.52e−8 is more than half a unit at 1, 2−50 = 8.88e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 8.88e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 38 significant bits.
e = 5, f = 50
e−18 = 1.52e−8 is more than half a unit at 1, 2−51 = 4.44e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.44e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 39 significant bits.
e = 5, f = 51
e−18 = 1.52e−8 is more than half a unit at 1, 2−52 = 2.22e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.22e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 40 significant bits.
e = 5, f = 52
e−18 = 1.52e−8 is more than half a unit at 1, 2−53 = 1.11e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.11e−16, and so is p0 − 1, against a gradient of 3.05e−8.
e−18 is below the smallest normal number, 6.1e−5, so it keeps only 41 significant bits.
e = 6, f = 1
With 1 fraction bit the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−2 = 0.25, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 2 significant bits.
e = 6, f = 2
With 2 fraction bits the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−3 = 0.125, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 3 significant bits.
e = 6, f = 3
e−18 = 1.52e−8 is less than half a unit at 1, 2−4 = 0.0625, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 4 significant bits.
e = 6, f = 4
e−18 = 1.52e−8 is less than half a unit at 1, 2−5 = 0.0313, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 5 significant bits.
e = 6, f = 5
e−18 = 1.52e−8 is less than half a unit at 1, 2−6 = 0.0156, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 6 significant bits.
e = 6, f = 6
e−18 = 1.52e−8 is less than half a unit at 1, 2−7 = 0.00781, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 7 significant bits.
e = 6, f = 7
e−18 = 1.52e−8 is less than half a unit at 1, 2−8 = 0.00391, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 8 significant bits.
e = 6, f = 8
e−18 = 1.52e−8 is less than half a unit at 1, 2−9 = 0.00195, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 9 significant bits.
e = 6, f = 9
e−18 = 1.52e−8 is less than half a unit at 1, 2−10 = 9.77e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 10 significant bits.
e = 6, f = 10
e−18 = 1.52e−8 is less than half a unit at 1, 2−11 = 4.88e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 11 significant bits.
e = 6, f = 11
e−18 = 1.52e−8 is less than half a unit at 1, 2−12 = 2.44e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 12 significant bits.
e = 6, f = 12
e−18 = 1.52e−8 is less than half a unit at 1, 2−13 = 1.22e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 13 significant bits.
e = 6, f = 13
e−18 = 1.52e−8 is less than half a unit at 1, 2−14 = 6.1e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 14 significant bits.
e = 6, f = 14
e−18 = 1.52e−8 is less than half a unit at 1, 2−15 = 3.05e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 15 significant bits.
e = 6, f = 15
e−18 = 1.52e−8 is less than half a unit at 1, 2−16 = 1.53e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 16 significant bits.
e = 6, f = 16
e−18 = 1.52e−8 is less than half a unit at 1, 2−17 = 7.63e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 17 significant bits.
e = 6, f = 17
e−18 = 1.52e−8 is less than half a unit at 1, 2−18 = 3.81e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 18 significant bits.
e = 6, f = 18
e−18 = 1.52e−8 is less than half a unit at 1, 2−19 = 1.91e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 19 significant bits.
e = 6, f = 19
e−18 = 1.52e−8 is less than half a unit at 1, 2−20 = 9.54e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 20 significant bits.
e = 6, f = 20
e−18 = 1.52e−8 is less than half a unit at 1, 2−21 = 4.77e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 21 significant bits.
e = 6, f = 21
e−18 = 1.52e−8 is less than half a unit at 1, 2−22 = 2.38e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 22 significant bits.
e = 6, f = 22
e−18 = 1.52e−8 is less than half a unit at 1, 2−23 = 1.19e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 23 significant bits.
e = 6, f = 23
e−18 = 1.52e−8 is less than half a unit at 1, 2−24 = 5.96e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 24 significant bits.
e = 6, f = 24
e−18 = 1.52e−8 is less than half a unit at 1, 2−25 = 2.98e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 25 significant bits.
e = 6, f = 25
e−18 = 1.52e−8 is more than half a unit at 1, 2−26 = 1.49e−8, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.49e−8, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 26 significant bits.
e = 6, f = 26
e−18 = 1.52e−8 is more than half a unit at 1, 2−27 = 7.45e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.45e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 27 significant bits.
e = 6, f = 27
e−18 = 1.52e−8 is more than half a unit at 1, 2−28 = 3.73e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.73e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 28 significant bits.
e = 6, f = 28
e−18 = 1.52e−8 is more than half a unit at 1, 2−29 = 1.86e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.86e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 29 significant bits.
e = 6, f = 29
e−18 = 1.52e−8 is more than half a unit at 1, 2−30 = 9.31e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.31e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 30 significant bits.
e = 6, f = 30
e−18 = 1.52e−8 is more than half a unit at 1, 2−31 = 4.66e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.66e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 31 significant bits.
e = 6, f = 31
e−18 = 1.52e−8 is more than half a unit at 1, 2−32 = 2.33e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.33e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 32 significant bits.
e = 6, f = 32
e−18 = 1.52e−8 is more than half a unit at 1, 2−33 = 1.16e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.16e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 33 significant bits.
e = 6, f = 33
e−18 = 1.52e−8 is more than half a unit at 1, 2−34 = 5.82e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.82e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 34 significant bits.
e = 6, f = 34
e−18 = 1.52e−8 is more than half a unit at 1, 2−35 = 2.91e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.91e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 35 significant bits.
e = 6, f = 35
e−18 = 1.52e−8 is more than half a unit at 1, 2−36 = 1.46e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.46e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 36 significant bits.
e = 6, f = 36
e−18 = 1.52e−8 is more than half a unit at 1, 2−37 = 7.28e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.28e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 37 significant bits.
e = 6, f = 37
e−18 = 1.52e−8 is more than half a unit at 1, 2−38 = 3.64e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.64e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 38 significant bits.
e = 6, f = 38
e−18 = 1.52e−8 is more than half a unit at 1, 2−39 = 1.82e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.82e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 39 significant bits.
e = 6, f = 39
e−18 = 1.52e−8 is more than half a unit at 1, 2−40 = 9.09e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.09e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 40 significant bits.
e = 6, f = 40
e−18 = 1.52e−8 is more than half a unit at 1, 2−41 = 4.55e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.55e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 41 significant bits.
e = 6, f = 41
e−18 = 1.52e−8 is more than half a unit at 1, 2−42 = 2.27e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.27e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 42 significant bits.
e = 6, f = 42
e−18 = 1.52e−8 is more than half a unit at 1, 2−43 = 1.14e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.14e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 43 significant bits.
e = 6, f = 43
e−18 = 1.52e−8 is more than half a unit at 1, 2−44 = 5.68e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.68e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 44 significant bits.
e = 6, f = 44
e−18 = 1.52e−8 is more than half a unit at 1, 2−45 = 2.84e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.84e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 45 significant bits.
e = 6, f = 45
e−18 = 1.52e−8 is more than half a unit at 1, 2−46 = 1.42e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.42e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 46 significant bits.
e = 6, f = 46
e−18 = 1.52e−8 is more than half a unit at 1, 2−47 = 7.11e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.11e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 47 significant bits.
e = 6, f = 47
e−18 = 1.52e−8 is more than half a unit at 1, 2−48 = 3.55e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.55e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 48 significant bits.
e = 6, f = 48
e−18 = 1.52e−8 is more than half a unit at 1, 2−49 = 1.78e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.78e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 49 significant bits.
e = 6, f = 49
e−18 = 1.52e−8 is more than half a unit at 1, 2−50 = 8.88e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 8.88e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 50 significant bits.
e = 6, f = 50
e−18 = 1.52e−8 is more than half a unit at 1, 2−51 = 4.44e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.44e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 51 significant bits.
e = 6, f = 51
e−18 = 1.52e−8 is more than half a unit at 1, 2−52 = 2.22e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.22e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 52 significant bits.
e = 6, f = 52
e−18 = 1.52e−8 is more than half a unit at 1, 2−53 = 1.11e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.11e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 53 significant bits.
e = 8, f = 1
With 1 fraction bit the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−2 = 0.25, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 2 significant bits.
e = 8, f = 2
With 2 fraction bits the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−3 = 0.125, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 3 significant bits.
e = 8, f = 3
e−18 = 1.52e−8 is less than half a unit at 1, 2−4 = 0.0625, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 4 significant bits.
e = 8, f = 4
e−18 = 1.52e−8 is less than half a unit at 1, 2−5 = 0.0313, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 5 significant bits.
e = 8, f = 5
e−18 = 1.52e−8 is less than half a unit at 1, 2−6 = 0.0156, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 6 significant bits.
e = 8, f = 6
e−18 = 1.52e−8 is less than half a unit at 1, 2−7 = 0.00781, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 7 significant bits.
e = 8, f = 7, bfloat16
e−18 = 1.52e−8 is less than half a unit at 1, 2−8 = 0.00391, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 8 significant bits.
e = 8, f = 8
e−18 = 1.52e−8 is less than half a unit at 1, 2−9 = 0.00195, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 9 significant bits.
e = 8, f = 9
e−18 = 1.52e−8 is less than half a unit at 1, 2−10 = 9.77e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 10 significant bits.
e = 8, f = 10, tf32
e−18 = 1.52e−8 is less than half a unit at 1, 2−11 = 4.88e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 11 significant bits.
e = 8, f = 11
e−18 = 1.52e−8 is less than half a unit at 1, 2−12 = 2.44e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 12 significant bits.
e = 8, f = 12
e−18 = 1.52e−8 is less than half a unit at 1, 2−13 = 1.22e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 13 significant bits.
e = 8, f = 13
e−18 = 1.52e−8 is less than half a unit at 1, 2−14 = 6.1e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 14 significant bits.
e = 8, f = 14
e−18 = 1.52e−8 is less than half a unit at 1, 2−15 = 3.05e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 15 significant bits.
e = 8, f = 15
e−18 = 1.52e−8 is less than half a unit at 1, 2−16 = 1.53e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 16 significant bits.
e = 8, f = 16
e−18 = 1.52e−8 is less than half a unit at 1, 2−17 = 7.63e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 17 significant bits.
e = 8, f = 17
e−18 = 1.52e−8 is less than half a unit at 1, 2−18 = 3.81e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 18 significant bits.
e = 8, f = 18
e−18 = 1.52e−8 is less than half a unit at 1, 2−19 = 1.91e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 19 significant bits.
e = 8, f = 19
e−18 = 1.52e−8 is less than half a unit at 1, 2−20 = 9.54e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 20 significant bits.
e = 8, f = 20
e−18 = 1.52e−8 is less than half a unit at 1, 2−21 = 4.77e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 21 significant bits.
e = 8, f = 21
e−18 = 1.52e−8 is less than half a unit at 1, 2−22 = 2.38e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 22 significant bits.
e = 8, f = 22
e−18 = 1.52e−8 is less than half a unit at 1, 2−23 = 1.19e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 23 significant bits.
e = 8, f = 23, binary32
e−18 = 1.52e−8 is less than half a unit at 1, 2−24 = 5.96e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 24 significant bits.
e = 8, f = 24
e−18 = 1.52e−8 is less than half a unit at 1, 2−25 = 2.98e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 25 significant bits.
e = 8, f = 25
e−18 = 1.52e−8 is more than half a unit at 1, 2−26 = 1.49e−8, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.49e−8, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 26 significant bits.
e = 8, f = 26
e−18 = 1.52e−8 is more than half a unit at 1, 2−27 = 7.45e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.45e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 27 significant bits.
e = 8, f = 27
e−18 = 1.52e−8 is more than half a unit at 1, 2−28 = 3.73e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.73e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 28 significant bits.
e = 8, f = 28
e−18 = 1.52e−8 is more than half a unit at 1, 2−29 = 1.86e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.86e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 29 significant bits.
e = 8, f = 29
e−18 = 1.52e−8 is more than half a unit at 1, 2−30 = 9.31e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.31e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 30 significant bits.
e = 8, f = 30
e−18 = 1.52e−8 is more than half a unit at 1, 2−31 = 4.66e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.66e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 31 significant bits.
e = 8, f = 31
e−18 = 1.52e−8 is more than half a unit at 1, 2−32 = 2.33e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.33e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 32 significant bits.
e = 8, f = 32
e−18 = 1.52e−8 is more than half a unit at 1, 2−33 = 1.16e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.16e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 33 significant bits.
e = 8, f = 33
e−18 = 1.52e−8 is more than half a unit at 1, 2−34 = 5.82e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.82e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 34 significant bits.
e = 8, f = 34
e−18 = 1.52e−8 is more than half a unit at 1, 2−35 = 2.91e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.91e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 35 significant bits.
e = 8, f = 35
e−18 = 1.52e−8 is more than half a unit at 1, 2−36 = 1.46e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.46e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 36 significant bits.
e = 8, f = 36
e−18 = 1.52e−8 is more than half a unit at 1, 2−37 = 7.28e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.28e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 37 significant bits.
e = 8, f = 37
e−18 = 1.52e−8 is more than half a unit at 1, 2−38 = 3.64e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.64e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 38 significant bits.
e = 8, f = 38
e−18 = 1.52e−8 is more than half a unit at 1, 2−39 = 1.82e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.82e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 39 significant bits.
e = 8, f = 39
e−18 = 1.52e−8 is more than half a unit at 1, 2−40 = 9.09e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.09e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 40 significant bits.
e = 8, f = 40
e−18 = 1.52e−8 is more than half a unit at 1, 2−41 = 4.55e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.55e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 41 significant bits.
e = 8, f = 41
e−18 = 1.52e−8 is more than half a unit at 1, 2−42 = 2.27e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.27e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 42 significant bits.
e = 8, f = 42
e−18 = 1.52e−8 is more than half a unit at 1, 2−43 = 1.14e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.14e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 43 significant bits.
e = 8, f = 43
e−18 = 1.52e−8 is more than half a unit at 1, 2−44 = 5.68e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.68e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 44 significant bits.
e = 8, f = 44
e−18 = 1.52e−8 is more than half a unit at 1, 2−45 = 2.84e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.84e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 45 significant bits.
e = 8, f = 45
e−18 = 1.52e−8 is more than half a unit at 1, 2−46 = 1.42e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.42e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 46 significant bits.
e = 8, f = 46
e−18 = 1.52e−8 is more than half a unit at 1, 2−47 = 7.11e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.11e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 47 significant bits.
e = 8, f = 47
e−18 = 1.52e−8 is more than half a unit at 1, 2−48 = 3.55e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.55e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 48 significant bits.
e = 8, f = 48
e−18 = 1.52e−8 is more than half a unit at 1, 2−49 = 1.78e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.78e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 49 significant bits.
e = 8, f = 49
e−18 = 1.52e−8 is more than half a unit at 1, 2−50 = 8.88e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 8.88e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 50 significant bits.
e = 8, f = 50
e−18 = 1.52e−8 is more than half a unit at 1, 2−51 = 4.44e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.44e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 51 significant bits.
e = 8, f = 51
e−18 = 1.52e−8 is more than half a unit at 1, 2−52 = 2.22e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.22e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 52 significant bits.
e = 8, f = 52
e−18 = 1.52e−8 is more than half a unit at 1, 2−53 = 1.11e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.11e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 53 significant bits.
e = 11, f = 1
With 1 fraction bit the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−2 = 0.25, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 2 significant bits.
e = 11, f = 2
With 2 fraction bits the logit 9 is stored as 8, so both formulas compute the gradient for [8, −8, −8], not the exact value above. e−18 = 1.52e−8 is less than half a unit at 1, 2−3 = 0.125, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 3 significant bits.
e = 11, f = 3
e−18 = 1.52e−8 is less than half a unit at 1, 2−4 = 0.0625, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 4 significant bits.
e = 11, f = 4
e−18 = 1.52e−8 is less than half a unit at 1, 2−5 = 0.0313, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 5 significant bits.
e = 11, f = 5
e−18 = 1.52e−8 is less than half a unit at 1, 2−6 = 0.0156, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 6 significant bits.
e = 11, f = 6
e−18 = 1.52e−8 is less than half a unit at 1, 2−7 = 0.00781, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 7 significant bits.
e = 11, f = 7
e−18 = 1.52e−8 is less than half a unit at 1, 2−8 = 0.00391, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 8 significant bits.
e = 11, f = 8
e−18 = 1.52e−8 is less than half a unit at 1, 2−9 = 0.00195, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 9 significant bits.
e = 11, f = 9
e−18 = 1.52e−8 is less than half a unit at 1, 2−10 = 9.77e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 10 significant bits.
e = 11, f = 10
e−18 = 1.52e−8 is less than half a unit at 1, 2−11 = 4.88e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 11 significant bits.
e = 11, f = 11
e−18 = 1.52e−8 is less than half a unit at 1, 2−12 = 2.44e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 12 significant bits.
e = 11, f = 12
e−18 = 1.52e−8 is less than half a unit at 1, 2−13 = 1.22e−4, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 13 significant bits.
e = 11, f = 13
e−18 = 1.52e−8 is less than half a unit at 1, 2−14 = 6.1e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 14 significant bits.
e = 11, f = 14
e−18 = 1.52e−8 is less than half a unit at 1, 2−15 = 3.05e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 15 significant bits.
e = 11, f = 15
e−18 = 1.52e−8 is less than half a unit at 1, 2−16 = 1.53e−5, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 16 significant bits.
e = 11, f = 16
e−18 = 1.52e−8 is less than half a unit at 1, 2−17 = 7.63e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 17 significant bits.
e = 11, f = 17
e−18 = 1.52e−8 is less than half a unit at 1, 2−18 = 3.81e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 18 significant bits.
e = 11, f = 18
e−18 = 1.52e−8 is less than half a unit at 1, 2−19 = 1.91e−6, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 19 significant bits.
e = 11, f = 19
e−18 = 1.52e−8 is less than half a unit at 1, 2−20 = 9.54e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 20 significant bits.
e = 11, f = 20
e−18 = 1.52e−8 is less than half a unit at 1, 2−21 = 4.77e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 21 significant bits.
e = 11, f = 21
e−18 = 1.52e−8 is less than half a unit at 1, 2−22 = 2.38e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 22 significant bits.
e = 11, f = 22
e−18 = 1.52e−8 is less than half a unit at 1, 2−23 = 1.19e−7, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 23 significant bits.
e = 11, f = 23
e−18 = 1.52e−8 is less than half a unit at 1, 2−24 = 5.96e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 24 significant bits.
e = 11, f = 24
e−18 = 1.52e−8 is less than half a unit at 1, 2−25 = 2.98e−8, so each addition to the running sum rounds back to 1 and p0 − 1 is 0.
The two small exponentials are added to each other, not to 1, so each keeps its 25 significant bits.
e = 11, f = 25
e−18 = 1.52e−8 is more than half a unit at 1, 2−26 = 1.49e−8, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.49e−8, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 26 significant bits.
e = 11, f = 26
e−18 = 1.52e−8 is more than half a unit at 1, 2−27 = 7.45e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.45e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 27 significant bits.
e = 11, f = 27
e−18 = 1.52e−8 is more than half a unit at 1, 2−28 = 3.73e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.73e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 28 significant bits.
e = 11, f = 28
e−18 = 1.52e−8 is more than half a unit at 1, 2−29 = 1.86e−9, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.86e−9, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 29 significant bits.
e = 11, f = 29
e−18 = 1.52e−8 is more than half a unit at 1, 2−30 = 9.31e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.31e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 30 significant bits.
e = 11, f = 30
e−18 = 1.52e−8 is more than half a unit at 1, 2−31 = 4.66e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.66e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 31 significant bits.
e = 11, f = 31
e−18 = 1.52e−8 is more than half a unit at 1, 2−32 = 2.33e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.33e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 32 significant bits.
e = 11, f = 32
e−18 = 1.52e−8 is more than half a unit at 1, 2−33 = 1.16e−10, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.16e−10, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 33 significant bits.
e = 11, f = 33
e−18 = 1.52e−8 is more than half a unit at 1, 2−34 = 5.82e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.82e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 34 significant bits.
e = 11, f = 34
e−18 = 1.52e−8 is more than half a unit at 1, 2−35 = 2.91e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.91e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 35 significant bits.
e = 11, f = 35
e−18 = 1.52e−8 is more than half a unit at 1, 2−36 = 1.46e−11, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.46e−11, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 36 significant bits.
e = 11, f = 36
e−18 = 1.52e−8 is more than half a unit at 1, 2−37 = 7.28e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.28e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 37 significant bits.
e = 11, f = 37
e−18 = 1.52e−8 is more than half a unit at 1, 2−38 = 3.64e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.64e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 38 significant bits.
e = 11, f = 38
e−18 = 1.52e−8 is more than half a unit at 1, 2−39 = 1.82e−12, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.82e−12, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 39 significant bits.
e = 11, f = 39
e−18 = 1.52e−8 is more than half a unit at 1, 2−40 = 9.09e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 9.09e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 40 significant bits.
e = 11, f = 40
e−18 = 1.52e−8 is more than half a unit at 1, 2−41 = 4.55e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.55e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 41 significant bits.
e = 11, f = 41
e−18 = 1.52e−8 is more than half a unit at 1, 2−42 = 2.27e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.27e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 42 significant bits.
e = 11, f = 42
e−18 = 1.52e−8 is more than half a unit at 1, 2−43 = 1.14e−13, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.14e−13, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 43 significant bits.
e = 11, f = 43
e−18 = 1.52e−8 is more than half a unit at 1, 2−44 = 5.68e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 5.68e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 44 significant bits.
e = 11, f = 44
e−18 = 1.52e−8 is more than half a unit at 1, 2−45 = 2.84e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.84e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 45 significant bits.
e = 11, f = 45
e−18 = 1.52e−8 is more than half a unit at 1, 2−46 = 1.42e−14, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.42e−14, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 46 significant bits.
e = 11, f = 46
e−18 = 1.52e−8 is more than half a unit at 1, 2−47 = 7.11e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 7.11e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 47 significant bits.
e = 11, f = 47
e−18 = 1.52e−8 is more than half a unit at 1, 2−48 = 3.55e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 3.55e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 48 significant bits.
e = 11, f = 48
e−18 = 1.52e−8 is more than half a unit at 1, 2−49 = 1.78e−15, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.78e−15, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 49 significant bits.
e = 11, f = 49
e−18 = 1.52e−8 is more than half a unit at 1, 2−50 = 8.88e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 8.88e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 50 significant bits.
e = 11, f = 50
e−18 = 1.52e−8 is more than half a unit at 1, 2−51 = 4.44e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 4.44e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 51 significant bits.
e = 11, f = 51
e−18 = 1.52e−8 is more than half a unit at 1, 2−52 = 2.22e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 2.22e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 52 significant bits.
e = 11, f = 52, binary64
e−18 = 1.52e−8 is more than half a unit at 1, 2−53 = 1.11e−16, so the sum moves off 1. But p0 is rounded to a multiple of that same 1.11e−16, and so is p0 − 1, against a gradient of 3.05e−8.
The two small exponentials are added to each other, not to 1, so each keeps its 53 significant bits.
Arithmetic and reference values
The target-logit gradient is evaluated at logits [9, -9, -9], with class 0 as the target. These are the same Lean results used in Figure 4, with mpmath references at 256 bits.
I wouldn't pick one formula and assume it's the right choice at every precision. We need to consider the format, input range, intermediate precision and operation order together, and check the numerical guarantees for the implementation we actually use.
Case study II: a transformer block¶
For the final case study, I wanted to see what happens when these errors move through a model rather than appearing in an isolated operator. Attention combines matrix products, softmax, and weighted sums; in our JAX tests, even float64 attention computed its softmax in float32 on both devices, with relative output errors as large as \(8.6\times10^{-8}\). MLX and CPU ONNX Runtime showed similar errors, though we did not isolate their causes. To trace the calculation more closely, I built a small transformer block using GPT-2's layout: three tokens of width 4, causal attention, a width 8 MLP with tanh GELU, and five output classes. Class 2 is the target, with a loss over the real numbers of about \(2.9\times10^{-8}\). Lean recorded 362 intermediate values in each of 12 formats. The visualization follows the errors from the first layer normalization all the way to the loss gradient.
binary64, up to and including the first LayerNorm: the largest relative error is 1.4e−16, at normalized. No value is a wrong 0.
binary64, up to and including the attention: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including the first residual: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including the second LayerNorm: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including the MLP: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including the second residual: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including the final LayerNorm and the logits: the largest relative error is 4.8e−15, at weights · v. No value is a wrong 0.
binary64, up to and including both cross-entropy heads: the largest relative error is 1.2e−9, at gradient. No value is a wrong 0. Target gradient: standard −2.9058e−8 (relative error 1.2e−9), TorchLean −2.9058e−8 (relative error 2e−15); exact −2.906e−8.
posit32, up to and including the first LayerNorm: the largest relative error is 5.8e−9, at normalized. No value is a wrong 0.
posit32, up to and including the attention: the largest relative error is 1.7e−7, at weights · v. No value is a wrong 0.
posit32, up to and including the first residual: the largest relative error is 1.7e−7, at weights · v. No value is a wrong 0.
posit32, up to and including the second LayerNorm: the largest relative error is 1.7e−7, at weights · v. No value is a wrong 0.
posit32, up to and including the MLP: the largest relative error is 1.7e−7, at weights · v. No value is a wrong 0.
posit32, up to and including the second residual: the largest relative error is 1.7e−7, at weights · v. No value is a wrong 0.
posit32, up to and including the final LayerNorm and the logits: the largest relative error is 3e−7, at logits. No value is a wrong 0.
posit32, up to and including both cross-entropy heads: the largest relative error is 0.026, at gradient. No value is a wrong 0. Target gradient: standard −2.9802e−8 (relative error 0.026), TorchLean −2.9058e−8 (relative error 1.4e−8); exact −2.906e−8.
binary32, up to and including the first LayerNorm: the largest relative error is 7.8e−8, at normalized. No value is a wrong 0.
binary32, up to and including the attention: the largest relative error is 1.7e−6, at weights · v. No value is a wrong 0.
binary32, up to and including the first residual: the largest relative error is 1.7e−6, at weights · v. No value is a wrong 0.
binary32, up to and including the second LayerNorm: the largest relative error is 1.7e−6, at weights · v. No value is a wrong 0.
binary32, up to and including the MLP: the largest relative error is 4e−6, at 1 + tanh z. No value is a wrong 0.
binary32, up to and including the second residual: the largest relative error is 4e−6, at 1 + tanh z. No value is a wrong 0.
binary32, up to and including the final LayerNorm and the logits: the largest relative error is 4e−6, at 1 + tanh z. No value is a wrong 0.
binary32, up to and including both cross-entropy heads: the largest relative error is 4e−6, at 1 + tanh z. 4 values are 0 where the exact value rounded to binary32 is not (log sum, log p₂, loss, gradient). Target gradient: standard 0, TorchLean −2.9058e−8 (relative error 1.5e−6); exact −2.906e−8.
posit16, up to and including the first LayerNorm: the largest relative error is 3.5e−4, at normalized. No value is a wrong 0.
posit16, up to and including the attention: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including the first residual: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including the second LayerNorm: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including the MLP: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including the second residual: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including the final LayerNorm and the logits: the largest relative error is 0.0098, at v. No value is a wrong 0.
posit16, up to and including both cross-entropy heads: the largest relative error is 0.014, at gradient. 4 values are 0 where the exact value rounded to posit16 is not (log sum, log p₂, loss, gradient). Target gradient: standard 0, TorchLean −2.9337e−8 (relative error 0.0096); exact −2.906e−8.
tf32, up to and including the first LayerNorm: the largest relative error is 0.0012, at normalized. No value is a wrong 0.
tf32, up to and including the attention: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including the first residual: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including the second LayerNorm: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including the MLP: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including the second residual: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including the final LayerNorm and the logits: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
tf32, up to and including both cross-entropy heads: the largest relative error is 0.033, at weights · v. 4 values are 0 where the exact value rounded to tf32 is not (log sum, log p₂, loss, gradient). Target gradient: standard 0, TorchLean −2.9424e−8 (relative error 0.013); exact −2.906e−8.
binary16, up to and including the first LayerNorm: the largest relative error is 0.0012, at normalized. No value is a wrong 0.
binary16, up to and including the attention: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including the first residual: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including the second LayerNorm: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including the MLP: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including the second residual: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including the final LayerNorm and the logits: the largest relative error is 0.033, at weights · v. No value is a wrong 0.
binary16, up to and including both cross-entropy heads: the largest relative error is 0.033, at weights · v. No value is a wrong 0. 25 values are 0 because the exact value rounds to 0 in binary16. Target gradient: standard 0, TorchLean 0; exact −2.906e−8.
bfloat16, up to and including the first LayerNorm: the largest relative error is 0.0057, at 1/√(var + ε). No value is a wrong 0.
bfloat16, up to and including the attention: the largest relative error is 0.02, at k. No value is a wrong 0.
bfloat16, up to and including the first residual: the largest relative error is 0.02, at k. No value is a wrong 0.
bfloat16, up to and including the second LayerNorm: the largest relative error is 0.04, at x − mean. No value is a wrong 0.
bfloat16, up to and including the MLP: the largest relative error is 0.17, at 1 + tanh z. No value is a wrong 0.
bfloat16, up to and including the second residual: the largest relative error is 0.17, at 1 + tanh z. No value is a wrong 0.
bfloat16, up to and including the final LayerNorm and the logits: the largest relative error is 0.17, at 1 + tanh z. No value is a wrong 0.
bfloat16, up to and including both cross-entropy heads: the largest relative error is 0.17, at 1 + tanh z. 4 values are 0 where the exact value rounded to bfloat16 is not (log sum, log p₂, loss, gradient). Target gradient: standard 0, TorchLean −2.6543e−8 (relative error 0.087); exact −2.906e−8.
posit8, up to and including the first LayerNorm: the largest relative error is 0.096, at normalized. No value is a wrong 0.
posit8, up to and including the attention: the largest relative error is 1.6, at v. No value is a wrong 0.
posit8, up to and including the first residual: the largest relative error is 1.6, at v. No value is a wrong 0.
posit8, up to and including the second LayerNorm: the largest relative error is 1.6, at v. No value is a wrong 0.
posit8, up to and including the MLP: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to posit8 is not (1 + tanh z, GELU, GELU W₂ + b₂).
posit8, up to and including the second residual: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to posit8 is not (1 + tanh z, GELU, GELU W₂ + b₂).
posit8, up to and including the final LayerNorm and the logits: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to posit8 is not (1 + tanh z, GELU, GELU W₂ + b₂).
posit8, up to and including both cross-entropy heads: the largest relative error is 95, at gradient. 11 values are 0 where the exact value rounded to posit8 is not (1 + tanh z, GELU, GELU W₂ + b₂, log sum, log p₂, loss, gradient). Target gradient: standard 0, TorchLean −5.9605e−8 (relative error 1.1); exact −2.906e−8.
E4M3, up to and including the first LayerNorm: the largest relative error is 0.096, at normalized. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the attention: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the first residual: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the second LayerNorm: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the MLP: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the second residual: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including the final LayerNorm and the logits: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3, up to and including both cross-entropy heads: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 is not (1 + tanh z, GELU, GELU W₂ + b₂). 25 values are 0 because the exact value rounds to 0 in E4M3. Target gradient: standard 0, TorchLean 0; exact −2.906e−8. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the first LayerNorm: the largest relative error is 0.096, at normalized. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the attention: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the first residual: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the second LayerNorm: the largest relative error is 1.6, at v. No value is a wrong 0. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the MLP: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 FNUZ is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the second residual: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 FNUZ is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including the final LayerNorm and the logits: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 FNUZ is not (1 + tanh z, GELU, GELU W₂ + b₂). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E4M3 FNUZ, up to and including both cross-entropy heads: the largest relative error is 2.6, at 1 + tanh z. 7 values are 0 where the exact value rounded to E4M3 FNUZ is not (1 + tanh z, GELU, GELU W₂ + b₂). 25 values are 0 because the exact value rounds to 0 in E4M3 FNUZ. Target gradient: standard 0, TorchLean 0; exact −2.906e−8. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2, up to and including the first LayerNorm: the largest relative error is 0.25, at normalized. 3 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized).
E5M2, up to and including the attention: the largest relative error is 6.6, at weights · v. 4 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v).
E5M2, up to and including the first residual: the largest relative error is 6.6, at weights · v. 4 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v).
E5M2, up to and including the second LayerNorm: the largest relative error is 6.6, at weights · v. 5 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v).
E5M2, up to and including the MLP: the largest relative error is 6.6, at weights · v. 17 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v, 1 + tanh z, GELU).
E5M2, up to and including the second residual: the largest relative error is 6.6, at weights · v. 18 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP).
E5M2, up to and including the final LayerNorm and the logits: the largest relative error is 6.6, at weights · v. 20 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP, logits).
E5M2, up to and including both cross-entropy heads: the largest relative error is 6.6, at weights · v. 20 values are 0 where the exact value rounded to E5M2 is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP, logits). 25 values are 0 because the exact value rounds to 0 in E5M2. Target gradient: standard 0, TorchLean 0; exact −2.906e−8.
E5M2 FNUZ, up to and including the first LayerNorm: the largest relative error is 0.25, at normalized. 3 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the attention: the largest relative error is 6.6, at weights · v. 4 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the first residual: the largest relative error is 6.6, at weights · v. 4 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the second LayerNorm: the largest relative error is 6.6, at weights · v. 5 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the MLP: the largest relative error is 6.6, at weights · v. 17 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v, 1 + tanh z, GELU). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the second residual: the largest relative error is 6.6, at weights · v. 18 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including the final LayerNorm and the logits: the largest relative error is 6.6, at weights · v. 20 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP, logits). In this format exp and log are FloatLib's approximations, not the exact value rounded once.
E5M2 FNUZ, up to and including both cross-entropy heads: the largest relative error is 350, at gradient. 20 values are 0 where the exact value rounded to E5M2 FNUZ is not (mean, x − mean, normalized, v, 1 + tanh z, GELU, x + MLP, logits). 16 values are 0 because the exact value rounds to 0 in E5M2 FNUZ. Target gradient: standard 0, TorchLean −7.6294e−6 (relative error 260); exact −2.906e−8. In this format exp and log are FloatLib's approximations, not the exact value rounded once.
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
LayerNorm, attention, residual
LayerNorm, MLP with tanh-GELU, residual
final LayerNorm and logits, last token
standard cross-entropy: softmax, log of the sum, p − 1
TorchLean's cross-entropy: pivot, log1p of the tail, expm1
Table: every format, worst relative error by stage
| format | LayerNorm and attention | MLP | logits | standard head | TorchLean head | standard gradient | TorchLean gradient |
|---|---|---|---|---|---|---|---|
| binary64 | 4.8e−15 | 3e−15 | 1.5e−15 | 1.2e−9 | 3.5e−15 | −2.9058e−8 | −2.9058e−8 |
| posit32 | 1.7e−7 | 1.2e−7 | 3e−7 | 0.026 | 2.6e−7 | −2.9802e−8 | −2.9058e−8 |
| binary32 | 1.7e−6 | 4e−6 | 9.2e−7 | 2.8e−6; 4 wrong 0s | 2.8e−6 | 0 | −2.9058e−8 |
| posit16 | 0.0098 | 0.0047 | 0.0085 | 0.014; 4 wrong 0s | 0.014 | 0 | −2.9337e−8 |
| tf32 | 0.033 | 0.015 | 0.0081 | 0.016; 4 wrong 0s | 0.016 | 0 | −2.9424e−8 |
| binary16 | 0.033 | 0.015 | 0.0081 | 8.6e−4 | 8.6e−4 | 0 | 0 |
| bfloat16 | 0.02 | 0.17 | 0.017 | 0.1; 4 wrong 0s | 0.1 | 0 | −2.6543e−8 |
| posit8 | 1.6 | 2.6; 7 wrong 0s | 0.7 | 95; 4 wrong 0s | 95 | 0 | −5.9605e−8 |
| E4M3 | 1.6 | 2.6; 7 wrong 0s | 0.7 | 0.094 | 0.094 | 0 | 0 |
| E4M3 FNUZ | 1.6 | 2.6; 7 wrong 0s | 0.7 | 0.094 | 0.094 | 0 | 0 |
| E5M2 | 6.6; 4 wrong 0s | 0.78; 14 wrong 0s | 0.24; 2 wrong 0s | 0.32 | 0.32 | 0 | 0 |
| E5M2 FNUZ | 6.6; 4 wrong 0s | 0.78; 14 wrong 0s | 0.24; 2 wrong 0s | 350 | 350 | 0 | −7.6294e−6 |
Arithmetic and reference values
The pre-LayerNorm block has three tokens of width 4, causal attention, an MLP of width 8 with tanh-GELU, and five output classes with target class 2. Inputs and weights have at most two significant bits and magnitudes between 1/8 and 8, so every tested format represents them exactly. Error comes from arithmetic and rounding the GELU constants and LayerNorm epsilon, 2^-16. In binary formats, tanh uses FloatLib's approximation without an accuracy theorem; this also applies to exp and log in E4M3 and the FNUZ formats. Binary runs use TorchLean's Context. The posit program was checked bit for bit against that Context in six binary formats. References use mpmath at 256 bits.
In float32, TF32, bfloat16, and posit16, four values incorrectly became zero in the loss calculation: the log of the sum, the target log probability, the loss, and the target gradient. The earlier computations had rounding error but no incorrect zeros, NaNs, or infinities. Binary16 is different: zero was the correctly rounded loss because the true value was too small for that format. Several formats with 8 bits lost information earlier, especially around GELU. And repairing the loss does not undo errors from the rest of the block. In float32, the rewritten target gradient still differed from the real valued block by about \(1.5\times10^{-6}\) relatively, after rounding near 21 moved one logit by about \(9.5\times10^{-7}\). The trace let us follow that error back to the rounded logit.
Rewriting formulas, proving guarantees¶
The softmax fix made me want to try the same approach on the other failures. We tested alternative formulas that compute the same function over the reals but avoid cancellation or intermediate overflow in floating point. The table below shows the original formulas, the replacements we tried, and what we have proved about them in Lean.
Here, \(\sigma\) means sigmoid, \(\operatorname{fl}\) means rounding, and \(\mathrm{CDF}(x)\) is a cumulative distribution function. A once-rounded reference computes the exact result and rounds only at the end.
| Operation | Before / after | Lean proof |
|---|---|---|
| Cross-entropy target gradient | Before\(p_t-1\) After \(\begin{aligned}T&=\sum_{j\ne t}e^{z_j-z_t}\\L&=\operatorname{log1p}(T)\\g_t&=\operatorname{expm1}(-L)\end{aligned}\)The target has the largest logit. The underflow fallback is discussed below. | Tail rewrite: bound proved. Underflow fallback: bound pending. |
| GRPO KL penalty | Before\(e^d-d-1\) After \(\operatorname{expm1}(d)-d\) | Rewrite bound proved on a restricted domain. |
| tanh-GELU | Before\(\tfrac12 x(1+\tanh z)\) After \(x\,\sigma(2z)\) | Measured; bound pending. |
| Sigmoid | BeforeLibrary kernel After \(\begin{cases}\dfrac{e^x}{1+e^x},&x<0,\\[5pt]\dfrac{1}{1+e^{-x}},&x\ge0.\end{cases}\) | Once-rounded reference proved. |
| Soft-margin loss and gradient | Before\(\log(1+e^{-yx})\) After \(\begin{aligned}m&=\max(0,-yx)\\L&=m+\operatorname{log1p}(e^{-|yx|})\\g&=-y\,\sigma(-yx)\end{aligned}\) | Once-rounded gradient proved. |
| Weibull survival probability | Before\(1-\operatorname{CDF}(x)\) After \(e^{-(x/\lambda)^k}\)\(\lambda\) and \(k\) are the scale and shape parameters. | Once-rounded reference proved. |
| Variance | Before\(\overline{x^2}-\bar x^2\) After \(\begin{aligned}c_i&=x_i-\bar x\\v&=\overline{c^2}-\bar c^2\end{aligned}\)Corrected two-pass form. | Once-rounded reference proved. |
| Diffusion noise level | Before\(\sqrt{1-\bar\alpha}\) After \(\begin{aligned}s&=\sum_i\operatorname{log1p}(-\beta_i)\\q&=\sqrt{-\operatorname{expm1}(s)}\end{aligned}\)\(\beta_i\) are the noise rates; \(\bar\alpha=\prod_i(1-\beta_i)\). | Measured; bound pending. |
| Sums in float16 | Before\(\begin{aligned}s_0&=0\\s_{i+1}&=\operatorname{fl}(s_i+x_i)\end{aligned}\) After \(\operatorname{fl}\!\left(\sum_i x_i\right)\)An exact sum rounded once, or a wider accumulator. | Planned. |
| Reciprocal square root and floor division | Before\(\begin{gathered}\operatorname{fl}(1/\operatorname{fl}(\sqrt{x}))\\\lfloor\operatorname{fl}(a/b)\rfloor\end{gathered}\) After \(\begin{gathered}\operatorname{fl}(1/\sqrt{x})\\\operatorname{fl}(\lfloor a/b\rfloor)\end{gathered}\)\(x>0\) and \(b\ne0\), respectively. | One-rounding program proved. |
The small exponentials in the softmax rewrite can still underflow. TorchLean therefore also has a fallback that combines them through their logarithms and is used only when every output is finite. For our worked input, float32 keeps the same answer, while binary16 recovers the correctly rounded gradient \(-2^{-24}\). We proved that the fallback preserves finiteness whenever the original computation is finite, for every supported scalar type and class count. A comparably tight general error bound for this fallback is still pending.
What I hope comes next¶
I want to keep pushing this with TorchLean and FloatLib, from individual operators to training code and kernels. That means getting tighter bounds and checking how well the modeled arithmetic matches the hardware. I'd also like to understand which local errors actually change a full training run.
I think the future here is bright : ) Verification can help us find numerical bugs at scale, test alternative formulas, and prove useful guarantees about the fixes. I'd love to see these checks become part of everyday ML development, so that changing a kernel or a number format comes with a check of its numerical behavior.
I'd be very happy to work with more experts in numerical analysis and floating-point arithmetic on better formulas and tighter bounds. If this is your area, I'd love to compare notes and work on these problems together.