Function formatFloatHexadecimal [src]

Prototype

pub fn formatFloatHexadecimal( value: anytype, options: FormatOptions, writer: anytype, ) !void

Parameters

options: FormatOptions

Source

pub fn formatFloatHexadecimal( value: anytype, options: FormatOptions, writer: anytype, ) !void { if (math.signbit(value)) { try writer.writeByte('-'); } if (math.isNan(value)) { return writer.writeAll("nan"); } if (math.isInf(value)) { return writer.writeAll("inf"); } const T = @TypeOf(value); const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); const mantissa_bits = math.floatMantissaBits(T); const fractional_bits = math.floatFractionalBits(T); const exponent_bits = math.floatExponentBits(T); const mantissa_mask = (1 << mantissa_bits) - 1; const exponent_mask = (1 << exponent_bits) - 1; const exponent_bias = (1 << (exponent_bits - 1)) - 1; const as_bits = @as(TU, @bitCast(value)); var mantissa = as_bits & mantissa_mask; var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask)); const is_denormal = exponent == 0 and mantissa != 0; const is_zero = exponent == 0 and mantissa == 0; if (is_zero) { // Handle this case here to simplify the logic below. try writer.writeAll("0x0"); if (options.precision) |precision| { if (precision > 0) { try writer.writeAll("."); try writer.writeByteNTimes('0', precision); } } else { try writer.writeAll(".0"); } try writer.writeAll("p0"); return; } if (is_denormal) { // Adjust the exponent for printing. exponent += 1; } else { if (fractional_bits == mantissa_bits) mantissa |= 1 << fractional_bits; // Add the implicit integer bit. } const mantissa_digits = (fractional_bits + 3) / 4; // Fill in zeroes to round the fraction width to a multiple of 4. mantissa <<= mantissa_digits * 4 - fractional_bits; if (options.precision) |precision| { // Round if needed. if (precision < mantissa_digits) { // We always have at least 4 extra bits. var extra_bits = (mantissa_digits - precision) * 4; // The result LSB is the Guard bit, we need two more (Round and // Sticky) to round the value. while (extra_bits > 2) { mantissa = (mantissa >> 1) | (mantissa & 1); extra_bits -= 1; } // Round to nearest, tie to even. mantissa |= @intFromBool(mantissa & 0b100 != 0); mantissa += 1; // Drop the excess bits. mantissa >>= 2; // Restore the alignment. mantissa <<= @as(math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4)); const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0; // Prefer a normalized result in case of overflow. if (overflow) { mantissa >>= 1; exponent += 1; } } } // +1 for the decimal part. var buf: [1 + mantissa_digits]u8 = undefined; _ = formatIntBuf(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits }); try writer.writeAll("0x"); try writer.writeByte(buf[0]); const trimmed = mem.trimRight(u8, buf[1..], "0"); if (options.precision) |precision| { if (precision > 0) try writer.writeAll("."); } else if (trimmed.len > 0) { try writer.writeAll("."); } try writer.writeAll(trimmed); // Add trailing zeros if explicitly requested. if (options.precision) |precision| if (precision > 0) { if (precision > trimmed.len) try writer.writeByteNTimes('0', precision - trimmed.len); }; try writer.writeAll("p"); try formatInt(exponent - exponent_bias, 10, .lower, .{}, writer); }