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.

generic_fmod

fmod.generic_fmod
inline fn generic_fmod(comptime T: type, x: T, y: T) T

File

lib/compiler_rt/fmod.zig:261

Code

inline fn generic_fmod(comptime T: type, x: T, y: T) T {
    const bits = @typeInfo(T).float.bits;
    const uint = @Int(.unsigned, bits);
    comptime assert(T == f32 or T == f64);
    const digits = if (T == f32) 23 else 52;
    const exp_bits = if (T == f32) 9 else 12;
    const bits_minus_1 = bits - 1;
    const mask = if (T == f32) 0xff else 0x7ff;
    var ux: uint = @bitCast(x);
    var uy: uint = @bitCast(y);
    var ex: i32 = @intCast((ux >> digits) & mask);
    var ey: i32 = @intCast((uy >> digits) & mask);
    const sx = if (T == f32) @as(u32, @intCast(ux & 0x80000000)) else @as(i32, @intCast(ux >> bits_minus_1));
    var i: uint = undefined;

    if (uy << 1 == 0 or math.isNan(@as(T, @bitCast(uy))) or ex == mask)
        return (x * y) / (x * y);

    if (ux << 1 <= uy << 1) {
        if (ux << 1 == uy << 1)
            return 0 * x;
        return x;
    }

    // normalize x and y
    if (ex == 0) {
        i = ux << exp_bits;
        while (i >> bits_minus_1 == 0) : ({
            ex -= 1;
            i <<= 1;
        }) {}
        ux <<= @intCast(@as(u32, @bitCast(-ex + 1)));
    } else {
        ux &= math.maxInt(uint) >> exp_bits;
        ux |= 1 << digits;
    }
    if (ey == 0) {
        i = uy << exp_bits;
        while (i >> bits_minus_1 == 0) : ({
            ey -= 1;
            i <<= 1;
        }) {}
        uy <<= @intCast(@as(u32, @bitCast(-ey + 1)));
    } else {
        uy &= math.maxInt(uint) >> exp_bits;
        uy |= 1 << digits;
    }

    // x mod y
    while (ex > ey) : (ex -= 1) {
        i = ux -% uy;
        if (i >> bits_minus_1 == 0) {
            if (i == 0)
                return 0 * x;
            ux = i;
        }
        ux <<= 1;
    }
    i = ux -% uy;
    if (i >> bits_minus_1 == 0) {
        if (i == 0)
            return 0 * x;
        ux = i;
    }
    while (ux >> digits == 0) : ({
        ux <<= 1;
        ex -= 1;
    }) {}

    // scale result up
    if (ex > 0) {
        ux -%= 1 << digits;
        ux |= @as(uint, @as(u32, @bitCast(ex))) << digits;
    } else {
        ux >>= @intCast(@as(u32, @bitCast(-ex + 1)));
    }
    if (T == f32) {
        ux |= sx;
    } else {
        ux |= @as(uint, @intCast(sx)) << bits_minus_1;
    }
    return @bitCast(ux);
}