╭ math.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const builtin = @import("builtin"); 2 const std = @import("std"); 3 4 const c = std.c; 5 const math = std.math; 6 7 const testing = std.testing; 8 const expect = testing.expect; 9 const expectEqual = testing.expectEqual; 10 const expectApproxEqAbs = testing.expectApproxEqAbs; 11 const expectApproxEqRel = testing.expectApproxEqRel; 12 13 fn testModf(comptime T: type) !void { 14 const f = switch (T) { 15 f32 => c.modff, 16 f64 => c.modf, 17 c_longdouble => c.modfl, 18 else => @compileError("modf not implemented for " ++ @typeName(T)), 19 }; 20 21 var int: T = undefined; 22 const iptr = ∫ 23 const eps_val: comptime_float = @max(1e-6, math.floatEps(T)); 24 25 const normal_frac = f(@as(T, 1234.567), iptr); 26 // Account for precision error 27 const expected = 1234.567 - @as(T, 1234); 28 try expectApproxEqAbs(expected, normal_frac, eps_val); 29 try expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val); 30 31 // When `x` is a NaN, NaN is returned and `*iptr` is set to NaN 32 const nan_frac = f(math.nan(T), iptr); 33 try expect(math.isNan(nan_frac)); 34 try expect(math.isNan(iptr.*)); 35 36 // When `x` is positive infinity, +0 is returned and `*iptr` is set to 37 // positive infinity 38 const pos_zero_frac = f(math.inf(T), iptr); 39 try expectEqual(0.0, pos_zero_frac); 40 try expect(math.isPositiveInf(iptr.*)); 41 42 // When `x` is negative infinity, -0 is returned and `*iptr` is set to 43 // negative infinity 44 const neg_zero_frac = f(-math.inf(T), iptr); 45 try expectEqual(-0.0, neg_zero_frac); 46 try expect(math.isNegativeInf(iptr.*)); 47 48 // Return -0 when `x` is a negative integer 49 const nz_frac = f(@as(T, -1000.0), iptr); 50 try expectEqual(-0.0, nz_frac); 51 try expectEqual(@as(T, -1000.0), iptr.*); 52 53 // Return +0 when `x` is a positive integer 54 const pz_frac = f(@as(T, 1000.0), iptr); 55 try expectEqual(0.0, pz_frac); 56 try expectEqual(@as(T, 1000.0), iptr.*); 57 } 58 59 test "modf" { 60 try testModf(f64); 61 } 62 63 test "modff" { 64 if (builtin.cpu.arch == .x86 and builtin.target.os.tag == .windows and builtin.target.abi != .gnu) return; // mingw-only 65 66 try testModf(f32); 67 } 68 69 test "modfl" { 70 if (builtin.cpu.arch.isX86() and builtin.target.os.tag == .windows and builtin.target.abi != .gnu) return; // mingw-only 71 if (builtin.target.cpu.arch.isPowerPC()) return error.SkipZigTest; // TODO: see https://codeberg.org/ziglang/zig/issues/30976 72 73 try testModf(c_longdouble); 74 } 75 76 fn testRintSpecial(comptime T: type) !void { 77 const f = switch (T) { 78 f32 => c.rintf, 79 f64 => c.rint, 80 c_longdouble => c.rintl, 81 else => @compileError("rint not implemented for" ++ @typeName(T)), 82 }; 83 84 // For the special cases, x itself should be returned 85 try expectEqual(0.0, f(0.0)); 86 try expectEqual(-0.0, f(-0.0)); 87 try expectEqual(math.inf(T), f(math.inf(T))); 88 try expectEqual(-math.inf(T), f(-math.inf(T))); 89 try expect(math.isNan(f(math.nan(T)))); 90 } 91 92 fn testRintNormal(comptime T: type) !void { 93 const f = switch (T) { 94 f32 => c.rintf, 95 f64 => c.rint, 96 c_longdouble => c.rintl, 97 else => @compileError("rint not implemented for" ++ @typeName(T)), 98 }; 99 100 // Positive numbers round correctly 101 try expectEqual(@as(T, 42.0), f(42.2)); 102 try expectEqual(@as(T, 42.0), f(41.8)); 103 try expectEqual(@as(T, 16_777_216.0), f(16_777_215.6)); 104 105 // Negative numbers round correctly 106 try expectEqual(@as(T, -6.0), f(-5.9)); 107 try expectEqual(@as(T, -6.0), f(-6.1)); 108 // TODO: negative `long double`s close to `-n.5` seem to round to `-n.5` 109 // instead of either `-n.0` or `-(n-1).0` on NetBSD. For example, this 110 // case would round to `-16_777_215.5`. 111 if (!(T == c_longdouble and builtin.target.os.tag == .netbsd)) { 112 try expectEqual(@as(T, -16_777_215.0), f(-16_777_215.4)); 113 } 114 115 // No rounding needed test 116 try expectEqual(@as(T, 5.0), f(5.0)); 117 try expectEqual(@as(T, -10.0), f(-10.0)); 118 try expectEqual(@as(T, 0.0), f(0.0)); 119 120 // Very large numbers return unchanged 121 const large: T = 9007199254740992.0; // 2^53 122 try expectEqual(large, f(large)); 123 try expectEqual(-large, f(-large)); 124 125 // Small positive numbers round to zero 126 try expectEqual(@as(T, 0.0), f(0.3)); 127 128 // TODO: negative `long double`s close to `-n.5` seem to round to `-n.5` 129 // instead of either `-n.0` or `-(n-1).0` on NetBSD. For example, this 130 // case would round to `-0.5`. 131 if (!(T == c_longdouble and builtin.target.os.tag == .netbsd)) { 132 // Small negative numbers round to negative zero 133 try expectEqual(@as(T, -0.0), f(-0.3)); 134 } 135 136 // Exact half rounds to nearest even (banker's rounding) 137 try expectEqual(@as(T, 2.0), f(2.5)); 138 try expectEqual(@as(T, 4.0), f(3.5)); 139 } 140 141 test "rintf.special" { 142 try testRintSpecial(f32); 143 } 144 145 test "rintf.normal" { 146 try testRintNormal(f32); 147 } 148 149 test "rint.special" { 150 try testRintSpecial(f64); 151 } 152 153 test "rint.normal" { 154 try testRintNormal(f64); 155 } 156 157 test "rintl.special" { 158 if (builtin.target.cpu.arch.isPowerPC()) return error.SkipZigTest; // TODO: see https://codeberg.org/ziglang/zig/issues/30976 159 160 try testRintSpecial(c_longdouble); 161 } 162 163 test "rintl.normal" { 164 if (builtin.target.cpu.arch.isPowerPC()) return error.SkipZigTest; // TODO: see https://codeberg.org/ziglang/zig/issues/30976 165 166 try testRintNormal(c_longdouble); 167 } 168