std::rt::Float8

std::rt::Float8

The OCP FP8 formats F8E4M3 and F8E5M2 as library structs.

Contents

NameSummary
f32_bitsReturns the IEEE binary32 bit pattern of x.
bits_f32Returns the f32 whose IEEE binary32 bit pattern is b.
F8E4M3OCP E4M3, finite-only.
extend F8E4M3
F8E5M2OCP E5M2. 1 sign / 5 exponent / 2 mantissa, bias 15. IEEE-shaped: infinities AND NaN both present, unlike E4M3FN.
extend F8E5M2
extend F8E4M3
extend F8E5M2
verify_e4m3_roundtripEvery one of the 256 E4M3FN bit patterns survives bits -> f32 -> bits unchanged.
verify_e5m2_roundtripChecks that every non-NaN E5M2 bit pattern survives bits -> f32 -> bits unchanged.
verify_e4m3_knownSpot-check the values the OCP spec names explicitly.
verify_e5m2_knownSpot-checks the E5M2 encodings the OCP spec names: 0, 1, 2, max finite (57344), overflow to infinity, and -1.

f32_bits

fn f32_bits(x: f32) -> u32

Returns the IEEE binary32 bit pattern of x.

Parameters

  • x: the value

Notes

Currently a numeric as conversion, not a bit cast (see the TODO in the source), so it does not yet reinterpret the bits.

bits_f32

fn bits_f32(b: u32) -> f32

Returns the f32 whose IEEE binary32 bit pattern is b.

Parameters

  • b: the bit pattern

Notes

Currently a numeric as conversion, not a bit cast (see the TODO in the source).

F8E4M3

struct F8E4M3

OCP E4M3, finite-only. 1 sign / 4 exponent / 3 mantissa, bias 7.

Layout:  S EEEE MMM
Max finite:   448.0    (S.1111.110)
Min normal:   2^-6     (S.0001.000)
Min subnormal: 2^-9    (S.0000.001)
NaN:          S.1111.111  -- the ONLY NaN encoding
Infinity:     none. Overflow saturates to +/-448.

Precision, not range. This is the weights-and-activations format.

F8E4M3.BIAS

static BIAS: i32

Exponent bias.

F8E4M3.MANT

static MANT: u32

Number of mantissa bits.

F8E4M3.MAX_FIN

static MAX_FIN: f32

Largest finite magnitude, 448.0.

F8E4M3.NAN_BITS

static NAN_BITS: u8

Encoding of NaN.

F8E4M3.bits

var bits: u8

The raw 8-bit encoding: sign, 4 exponent bits, 3 mantissa bits.

extend F8E4M3

extend F8E4M3

F8E4M3.F8E4M3

fn F8E4M3(self)

Constructs a zero (all bits clear).

F8E4M3.F8E4M3

fn F8E4M3(self, v: f32)

Constructs the nearest E4M3 value to v, rounding to nearest even; overflow saturates to +/-448.

Parameters

  • v: the value to encode

F8E4M3.from_f32_bits

fn from_f32_bits(v: f32) -> u8

f32 -> E4M3FN, round-to-nearest-even, saturating.

Saturation rather than infinity is the whole point of the FN form: there is no inf encoding, so a value past 448 becomes 448, and only a NaN input produces a NaN output.

F8E4M3.to_f32

fn to_f32(self) -> f32

E4M3FN -> f32. Always exact: every E4M3 value is representable in binary32, so no rounding occurs and no mode is needed.

F8E4M3.is_nan

fn is_nan(self) -> bool

Returns whether the value is NaN: exponent and mantissa all ones, the only NaN encoding.

F8E4M3.is_zero

fn is_zero(self) -> bool

Returns whether the value is zero (positive or negative).

F8E4M3.op as

fn op as (self) -> f32

Converts to f32 with as; same as to_f32.

F8E5M2

struct F8E5M2

OCP E5M2. 1 sign / 5 exponent / 2 mantissa, bias 15. IEEE-shaped: infinities AND NaN both present, unlike E4M3FN.

Layout:  S EEEEE MM
Max finite:   57344.0  (S.11110.11)
Min normal:   2^-14
Min subnormal: 2^-16
Inf:          S.11111.00
NaN:          S.11111.xx  with xx != 00

Range, not precision. The exponent field is IDENTICAL to f16's,
which is why f16 <-> e5m2 is a shift rather than a
renormalization. This is the gradients format.

F8E5M2.BIAS

static BIAS: i32

Exponent bias.

F8E5M2.MANT

static MANT: u32

Number of mantissa bits.

F8E5M2.MAX_FIN

static MAX_FIN: f32

Largest finite magnitude, 57344.0.

F8E5M2.INF_BITS

static INF_BITS: u8

Encoding of positive infinity.

F8E5M2.bits

var bits: u8

The raw 8-bit encoding: sign, 5 exponent bits, 2 mantissa bits.

extend F8E5M2

extend F8E5M2

F8E5M2.F8E5M2

fn F8E5M2(self)

Constructs a zero (all bits clear).

F8E5M2.F8E5M2

fn F8E5M2(self, v: f32)

Constructs the nearest E5M2 value to v, rounding to nearest even; overflow gives an infinity.

Parameters

  • v: the value to encode

F8E5M2.from_f32_bits

fn from_f32_bits(v: f32) -> u8

f32 -> E5M2, round-to-nearest-even. Overflow produces INFINITY here, not saturation -- E5M2 has inf encodings and IEEE semantics.

F8E5M2.to_f32

fn to_f32(self) -> f32

E5M2 -> f32. Always exact.

F8E5M2.is_nan

fn is_nan(self) -> bool

Returns whether the value is a NaN: exponent all ones and a nonzero mantissa.

F8E5M2.is_inf

fn is_inf(self) -> bool

Returns whether the value is an infinity (either sign).

F8E5M2.is_zero

fn is_zero(self) -> bool

Returns whether the value is zero (positive or negative).

F8E5M2.op as

fn op as (self) -> f32

Converts to f32 with as; same as to_f32.

extend F8E4M3

extend F8E4M3

F8E4M3.op +

fn op + (self, const rhs: F8E4M3) -> f32

Adds after promoting both operands to f32; the result is an f32, not an F8E4M3.

Arithmetic returns f32 on purpose: narrowing back to fp8 after every operation would round at each step. Narrow once, at the final assignment.

F8E4M3.op -

fn op - (self, const rhs: F8E4M3) -> f32

Subtracts after promoting both operands to f32; the result is an f32, not an F8E4M3.

F8E4M3.op *

fn op * (self, const rhs: F8E4M3) -> f32

Multiplies after promoting both operands to f32; the result is an f32, not an F8E4M3.

F8E4M3.op /

fn op / (self, const rhs: F8E4M3) -> f32

Divides after promoting both operands to f32; the result is an f32, not an F8E4M3.

F8E4M3.op ==

fn op == (self, const rhs: F8E4M3) -> bool

Bitwise equality, NOT numeric. Two encodings of the same value do not exist in E4M3FN, so this differs from numeric equality only at NaN (which compares unequal to itself numerically) and signed zero (-0.0 == +0.0 numerically, different bits here). Compare through to_f32() when IEEE comparison semantics are what you want.

extend F8E5M2

extend F8E5M2

F8E5M2.op +

fn op + (self, const rhs: F8E5M2) -> f32

Adds after promoting both operands to f32; the result is an f32, not an F8E5M2.

Arithmetic returns f32 on purpose: narrowing back to fp8 after every operation would round at each step. Narrow once, at the final assignment.

F8E5M2.op -

fn op - (self, const rhs: F8E5M2) -> f32

Subtracts after promoting both operands to f32; the result is an f32, not an F8E5M2.

F8E5M2.op *

fn op * (self, const rhs: F8E5M2) -> f32

Multiplies after promoting both operands to f32; the result is an f32, not an F8E5M2.

F8E5M2.op /

fn op / (self, const rhs: F8E5M2) -> f32

Divides after promoting both operands to f32; the result is an f32, not an F8E5M2.

F8E5M2.op ==

fn op == (self, const rhs: F8E5M2) -> bool

Bitwise equality of the encodings, not IEEE numeric equality: a NaN equals an identical NaN here, and -0.0 differs from +0.0. Convert with to_f32 for numeric comparison.

verify_e4m3_roundtrip

fn verify_e4m3_roundtrip() -> bool

Every one of the 256 E4M3FN bit patterns survives bits -> f32 -> bits unchanged.

This is the half of the exhaustive test you can run WITHOUT
APFloat. It proves the two conversions are mutual inverses; it
does NOT prove either matches the OCP spec. For that, run the
same 256 patterns through APFloat's semFloat8E4M3FN in the
compiler and diff. Both halves are needed: mutually-inverse
conversions can still both be wrong in the same direction.

verify_e5m2_roundtrip

fn verify_e5m2_roundtrip() -> bool

Checks that every non-NaN E5M2 bit pattern survives bits -> f32 -> bits unchanged.

NaN payloads are skipped because they are not preserved.

Returns

true when every non-NaN encoding round-trips.

verify_e4m3_known

fn verify_e4m3_known() -> bool

Spot-check the values the OCP spec names explicitly. Cheap, and it catches a bias or shift that is off by one -- which round-trip testing alone cannot, since a consistent off-by-one is still self-inverse.

verify_e5m2_known

fn verify_e5m2_known() -> bool

Spot-checks the E5M2 encodings the OCP spec names: 0, 1, 2, max finite (57344), overflow to infinity, and -1.

Returns

true when every spot-check encodes to the expected bit pattern.

Generated from Kairo source, Apache-2.0 WITH AdditionRef-Kairo-Runtime-exception.