Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

floatFromBigInt

float_from_int.floatFromBigInt
pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T

File

lib/compiler_rt/float_from_int.zig:64

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 => {},
    }

    // sign implicit fraction round sticky
    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));
}