Expand description
Software e2m1 conversion, on u32 bit patterns only, so a backend with no 4-bit float type
can still decode and encode fp4 from the bits in a word.
This is the fp4 counterpart of cubecl_core::post_processing::minifloat, and it exists for the
same reason: e2m1 conversion is a CUDA intrinsic and nothing else. Every other backend either
has no 4-bit float type at all or can only move one around, so a quantized kernel that reaches
for e2m1x2::from_bits runs on one vendor. The arithmetic below runs everywhere.
It does not go through the general minifloat path. That one reconstructs an f32 bit pattern
field by field, which is the only tractable way to cover eight exponent bits; e2m1 has four
codes per sign and its eight magnitudes are {0, 0.5, 1, 1.5, 2, 3, 4, 6}, small enough that
decoding is one select over the subnormal arm and encoding is a count of the midpoints a
magnitude clears.
Modules§
- e2m1_
bits_ to_ float - e2m1_
bytes_ to_ f16 - e2m1_
packed_ bits_ to_ float - e2m1_
words_ to_ f16 - e2m1_
words_ to_ f16_ placed - float_
to_ e2m1_ bits
Structs§
- Lower
Fp4Cast - Lowers every cast from or to
e2m1x2onto the software codec, for a backend that has no native fp4 conversion.
Constants§
- E2M1_
F16_ LIFT - What a code placed as an
f16near the bottom of its range, its sign, exponent and mantissa moved onto thef16’s own, is short of its value by:2^14, the gap between ane2m1exponent of zero and anf16one.
Functions§
- e2m1_
bits_ to_ float - Decode one
e2m1code per lane, held in the low nibble of each lane ofcode. - e2m1_
bytes_ to_ f16 e2m1_words_to_f16for bytes that do not fill a word, onee2m1x2per lane ofbytes: the high nibble moves up to the second half of the word first, one more mask and shift a pair.- e2m1_
packed_ bits_ to_ float - Decode the
Ne2m1codes packed into the low4 * Nbits ofword, lowest nibble first. - e2m1_
words_ to_ f16 - Decode the eight codes of each word of
words, lowest nibble first, tof16. - e2m1_
words_ to_ f16_ placed - The eight codes of each word of
words, lowest nibble first, placed asf16eachE2M1_F16_LIFTshort of its value, exactly: what a caller that multiplies the values by a factor anyway, a block scale, takes, multiplying the lift into that factor once rather than paying a multiply a value. - float_
to_ e2m1_ bits - Encode one
e2m1code per lane into the low nibble of each lane, rounding to nearest with ties to even and saturating at±6.