Create a floating-point quantization map with configurable bit layout. Generates a lookup table for a custom floating-point format following IEEE 754-like encoding with configurable exponent and mantissa (precision) bits. Despite the name, this function handles any total bit width (incl
(signed=True, exponent_bits=5, precision_bits=2, total_bits=8)
| 225 | |
| 226 | |
| 227 | def create_fp8_map(signed=True, exponent_bits=5, precision_bits=2, total_bits=8): |
| 228 | """Create a floating-point quantization map with configurable bit layout. |
| 229 | |
| 230 | Generates a lookup table for a custom floating-point format following IEEE 754-like encoding |
| 231 | with configurable exponent and mantissa (precision) bits. Despite the name, this function |
| 232 | handles any total bit width (including FP4 when called with ``total_bits=4``). |
| 233 | |
| 234 | The encoding uses: |
| 235 | - Exponent bias: ``2^(exponent_bits - 1)`` |
| 236 | - Normal values: ``(1 + mantissa) * 2^(exponent - bias - 1)`` |
| 237 | - Subnormal values (exponent field = 0): ``mantissa * 2^(-bias)`` |
| 238 | |
| 239 | Note: The values in the returned tensor are normalized by dividing by the maximum value, |
| 240 | so the actual represented range is [-1, 1]. |
| 241 | |
| 242 | For the FP4 type used in bitsandbytes (2 exponent bits, 1 mantissa bit, signed): |
| 243 | ``create_fp8_map(signed=True, exponent_bits=2, precision_bits=1, total_bits=4)`` |
| 244 | |
| 245 | Args: |
| 246 | signed: Whether the format includes a sign bit. |
| 247 | exponent_bits: Number of bits for the exponent field. |
| 248 | precision_bits: Number of bits for the mantissa (precision/fraction) field. |
| 249 | total_bits: Total number of bits per value (must equal sign + exponent + precision). |
| 250 | |
| 251 | Returns: |
| 252 | A 256-element tensor of sorted quantization levels normalized to [-1, 1]. |
| 253 | For types with fewer than 8 bits, the remaining entries are zero-padded. |
| 254 | """ |
| 255 | e = exponent_bits |
| 256 | p = precision_bits |
| 257 | has_sign = 1 if signed else 0 |
| 258 | assert e + p == total_bits - has_sign |
| 259 | # the exponent is biased to 2^(e-1) -1 == 0 |
| 260 | evalues = [] |
| 261 | for i, val in enumerate(range(-(2 ** (exponent_bits - has_sign)), 2 ** (exponent_bits - has_sign), 1)): |
| 262 | evalues.append(2**val) |
| 263 | |
| 264 | values = [] |
| 265 | lst = list(itertools.product([0, 1], repeat=precision_bits)) |
| 266 | # for ev in evalues: |
| 267 | bias = 2 ** (exponent_bits - 1) |
| 268 | for evalue in range(2 ** (exponent_bits)): |
| 269 | for bit_pattern in lst: |
| 270 | value = 1 if evalue != 0 else 0 |
| 271 | for i, pval in enumerate(list(bit_pattern)): |
| 272 | value += pval * (2 ** -(i + 1)) |
| 273 | if evalue == 0: |
| 274 | # subnormals |
| 275 | value = value * 2**-(bias) |
| 276 | else: |
| 277 | # normals |
| 278 | value = value * 2 ** -(evalue - bias - 1) |
| 279 | values.append(value) |
| 280 | if signed: |
| 281 | values.append(-value) |
| 282 | |
| 283 | assert len(values) == 2**total_bits |
| 284 | values.sort() |
nothing calls this directly
no outgoing calls
no test coverage detected