feature. See also
. The project being documented here (as the example) is the Zig library itself.
float.FloatRepr
pub fn FloatRepr(comptime Float: type) type
File
Code
pub fn FloatRepr(comptime Float: type) type {
const fractional_bits = floatFractionalBits(Float);
const exponent_bits = floatExponentBits(Float);
return packed struct {
const Repr = @This();
mantissa: StoredMantissa,
exponent: BiasedExponent,
sign: std.math.Sign,
pub const StoredMantissa = @Int(.unsigned, floatMantissaBits(Float));
pub const Mantissa = @Int(.unsigned, 1 + fractional_bits);
pub const Exponent = @Int(.signed, exponent_bits);
pub const BiasedExponent = enum(@Int(.unsigned, exponent_bits)) {
denormal = 0,
min_normal = 1,
zero = (1 << (exponent_bits - 1)) - 1,
max_normal = (1 << exponent_bits) - 2,
infinite = (1 << exponent_bits) - 1,
_,
pub const Int = @typeInfo(BiasedExponent).@"enum".tag_type;
pub fn unbias(biased: BiasedExponent) Exponent {
switch (biased) {
.denormal => unreachable,
else => return @bitCast(@backingInt(biased) -% @backingInt(BiasedExponent.zero)),
.infinite => unreachable,
}
}
pub fn bias(unbiased: Exponent) BiasedExponent {
return @fromBackingInt(@intCast(@backingInt(BiasedExponent.zero) +% @as(Int, @bitCast(unbiased))));
}
};
pub const Normalized = struct {
fraction: Fraction,
exponent: Normalized.Exponent,
pub const Fraction = @Int(.unsigned, fractional_bits);
pub const Exponent = @Int(.signed, 1 + exponent_bits);
pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {
if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
.mantissa = 0,
.exponent = .infinite,
.sign = sign,
});
const mantissa = @as(Mantissa, 1 << fractional_bits) | normalized.fraction;
if (normalized.exponent < BiasedExponent.min_normal.unbias()) return @bitCast(Repr{
.mantissa = @truncate(std.math.shr(
Mantissa,
mantissa,
BiasedExponent.min_normal.unbias() - normalized.exponent,
)),
.exponent = .denormal,
.sign = sign,
});
return @bitCast(Repr{
.mantissa = @truncate(mantissa),
.exponent = .bias(@intCast(normalized.exponent)),
.sign = sign,
});
}
};
pub const Classified = union(enum) { normalized: Normalized, infinity, nan, invalid };
fn classify(repr: Repr) Classified {
return switch (repr.exponent) {
.denormal => {
const mantissa: Mantissa = repr.mantissa;
const shift = @clz(mantissa);
return .{ .normalized = .{
.fraction = @truncate(mantissa << shift),
.exponent = @as(Normalized.Exponent, comptime BiasedExponent.min_normal.unbias()) - shift,
} };
},
else => if (repr.mantissa <= std.math.maxInt(Normalized.Fraction)) .{ .normalized = .{
.fraction = @intCast(repr.mantissa),
.exponent = repr.exponent.unbias(),
} } else .invalid,
.infinite => switch (repr.mantissa) {
0 => .infinity,
else => .nan,
},
};
}
};
}