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.

impl

floor_ceil.impl
inline fn impl(comptime T: type, comptime op: enum

File

lib/compiler_rt/floor_ceil.zig:92

Code

inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T {
    const C = 1.0 / math.floatEps(T);
    const mantissa = math.floatMantissaBits(T);
    const mask = (1 << math.floatExponentBits(T)) - 1;
    const bias = (1 << (math.floatExponentBits(T) - 1)) - 1;

    const bits = @bitSizeOf(T);
    const U = @Int(.unsigned, bits);
    var u: U = @bitCast(x);
    switch (T) {
        f16, f32 => {
            const e = @as(@Int(.signed, bits), @intCast((u >> mantissa) & mask)) - bias;
            if (e >= mantissa) return x;

            if (e >= 0) {
                const m = (@as(U, 1) << @intCast(mantissa - e)) - 1;
                if (u & m == 0) return x;
                if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120);
                if (u >> bits - 1 == @intFromBool(op == .floor)) u += m;
                return @bitCast(u & ~m);
            } else {
                if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120);
                return switch (op) {
                    .floor => if (u >> bits - 1 == 0) 0.0 else if (u << 1 != 0) -1.0 else x,
                    .ceil => if (u >> bits - 1 != 0) -0.0 else if (u << 1 != 0) 1.0 else x,
                };
            }
        },
        f64, f80, f128 => {
            const e = (u >> mantissa) & mask;
            if (e >= bias + math.floatFractionalBits(T) or x == 0) return x;

            const positive = u >> @bitSizeOf(T) - 1 == 0;
            const y: T = if (positive)
                x + C - C - x
            else
                x - C + C - x;

            if (e <= bias - 1) {
                if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(y);
                return switch (op) {
                    .floor => if (positive) 0.0 else -1.0,
                    .ceil => if (positive) 1.0 else -0.0,
                };
            }
            switch (op) {
                .floor => if (y > 0) return x + y - 1,
                .ceil => if (y < 0) return x + y + 1,
            }
            return x + y;
        },
        else => unreachable,
    }
}