feature. See also
. The project being documented here (as the example) is the Zig library itself.
float_from_int.floatFromBigInt
pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T
File
Code
pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T {
switch (x.len) {
0 => return 0,
inline 1...4 => |limbs_len| {
const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) {
.little => x[0..limbs_len].*,
.big => switch (limbs_len) {
1 => .{x[0]},
2 => .{ x[1], x[0] },
3 => .{ x[2], x[1], x[0] },
4 => .{ x[3], x[2], x[1], x[0] },
else => comptime unreachable,
},
};
const I = @Int(signedness, 32 * limbs_len);
const int: I = @bitCast(low_to_high);
return @floatFromInt(int);
},
else => {},
}
const I = comptime @Int(
signedness,
@as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1,
);
const clrsb = clrsb: {
var clsb: usize = 0;
const sign_bits: u32 = switch (signedness) {
.signed => @bitCast(@as(i32, @bitCast(limb(x, x.len - 1))) >> 31),
.unsigned => 0,
};
for (0..x.len) |limb_index| {
const l = limb(x, x.len - 1 - limb_index) ^ sign_bits;
clsb += @clz(l);
if (l != 0) break;
}
break :clrsb clsb - @intFromBool(signedness == .signed);
};
const active_bits = 32 * x.len - clrsb;
const exponent = active_bits -| @bitSizeOf(I);
const exponent_limb = exponent / 32;
const sticky = for (0..exponent_limb) |limb_index| {
if (limb(x, limb_index) != 0) break true;
} else limb(x, exponent_limb) & ((@as(u32, 1) << @truncate(exponent)) - 1) != 0;
return math.ldexp(@as(T, @floatFromInt(
std.mem.readPackedInt(I, std.mem.sliceAsBytes(x), exponent, .native) | @intFromBool(sticky),
)), @intCast(exponent));
}