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.

extend_f80

extendf.extend_f80
pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80

File

lib/compiler_rt/extendf.zig:73

Code

pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 {
    const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits);
    const src_sig_bits = std.math.floatMantissaBits(src_t);
    const dst_int_bit = 0x8000000000000000;
    const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit

    const dst_exp_bias = 16383;

    const src_bits = @bitSizeOf(src_t);
    const src_exp_bits = src_bits - src_sig_bits - 1;
    const src_inf_exp = (1 << src_exp_bits) - 1;
    const src_exp_bias = src_inf_exp >> 1;

    const src_min_normal = 1 << src_sig_bits;
    const src_inf = src_inf_exp << src_sig_bits;
    const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
    const src_abs_mask = src_sign_mask - 1;
    const src_qnan = 1 << (src_sig_bits - 1);
    const src_nan_code = src_qnan - 1;

    var dst: std.math.F80 = undefined;

    // Break a into a sign and representation of the absolute value
    const a_abs = a & src_abs_mask;
    const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;

    if (a_abs -% src_min_normal < src_inf - src_min_normal) {
        // a is a normal number.
        // Extend to the destination type by shifting the significand and
        // exponent into the proper position and rebiasing the exponent.
        dst.exp = @intCast(a_abs >> src_sig_bits);
        dst.exp += dst_exp_bias - src_exp_bias;
        dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits);
        dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
    } else if (a_abs >= src_inf) {
        // a is NaN or infinity.
        // Conjure the result by beginning with infinity, then setting the qNaN
        // bit (if needed) and right-aligning the rest of the trailing NaN
        // payload field.
        dst.exp = 0x7fff;
        dst.fraction = dst_int_bit;
        dst.fraction |= @as(u64, a_abs & src_qnan) << (dst_sig_bits - src_sig_bits);
        dst.fraction |= @as(u64, a_abs & src_nan_code) << (dst_sig_bits - src_sig_bits);
    } else if (a_abs != 0) {
        // a is denormal.
        // renormalize the significand and clear the leading bit, then insert
        // the correct adjusted exponent in the destination type.
        const scale: u16 = @clz(a_abs) - @clz(@as(src_rep_t, src_min_normal));

        dst.fraction = @as(u64, a_abs) << @intCast(dst_sig_bits - src_sig_bits + scale);
        dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
        dst.exp = @truncate(a_abs >> @intCast(src_sig_bits - scale));
        dst.exp ^= 1;
        dst.exp |= dst_exp_bias - src_exp_bias - scale + 1;
    } else {
        // a is zero.
        dst.exp = 0;
        dst.fraction = 0;
    }

    dst.exp |= sign;
    return dst.toFloat();
}