authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-07-31 10:56:49+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-07-31 10:57:04+01:00
log64bf8bb146099b51d74635a1f116a913e442bcf4
tree2f9cba090e0fdea54b9bffdbd76e5c729756464d
parente664bf4d81e9266ee4749b5da88cab4554499bf6
signaturelock-open Commit is signed but in an unrecognized format.

std: stop relying on precision-losing coercions


5 files changed, 29 insertions(+), 25 deletions(-)

lib/std/math.zig+7-3
......@@ -1345,11 +1345,15 @@ pub fn lossyCast(comptime T: type, value: anytype) T {
13451345 }
13461346 },
13471347 .float, .comptime_float => {
1348 // In extreme cases, we probably need a language enhancement to be able to
1349 // specify a rounding mode here to prevent `@intFromFloat` panics.
1350 const max: @TypeOf(value) = @floatFromInt(maxInt(T));
1351 const min: @TypeOf(value) = @floatFromInt(minInt(T));
13481352 if (isNan(value)) {
13491353 return 0;
1350 } else if (value >= maxInt(T)) {
1354 } else if (value >= max) {
13511355 return maxInt(T);
1352 } else if (value <= minInt(T)) {
1356 } else if (value <= min) {
13531357 return minInt(T);
13541358 } else {
13551359 return @intFromFloat(value);
......@@ -1366,7 +1370,7 @@ test lossyCast {
13661370 try testing.expect(lossyCast(i16, 70000.0) == @as(i16, 32767));
13671371 try testing.expect(lossyCast(u32, @as(i16, -255)) == @as(u32, 0));
13681372 try testing.expect(lossyCast(i9, @as(u32, 200)) == @as(i9, 200));
1369 try testing.expect(lossyCast(u32, @as(f32, maxInt(u32))) == maxInt(u32));
1373 try testing.expect(lossyCast(u32, @as(f32, @floatFromInt(maxInt(u32)))) == maxInt(u32));
13701374 try testing.expect(lossyCast(u32, nan(f32)) == 0);
13711375}
13721376
lib/std/math/gamma.zig+16-16
......@@ -189,19 +189,19 @@ fn series(comptime T: type, abs: T) T {
189189 2.5066282746310002701649081771338373386264310793408,
190190 };
191191 const denominator = [_]T{
192 0,
193 39916800,
194 120543840,
195 150917976,
196 105258076,
197 45995730,
198 13339535,
199 2637558,
200 357423,
201 32670,
202 1925,
203 66,
204 1,
192 0.0,
193 39916800.0,
194 120543840.0,
195 150917976.0,
196 105258076.0,
197 45995730.0,
198 13339535.0,
199 2637558.0,
200 357423.0,
201 32670.0,
202 1925.0,
203 66.0,
204 1.0,
205205 };
206206 var num: T = 0;
207207 var den: T = 0;
......@@ -244,9 +244,9 @@ const expectApproxEqRel = std.testing.expectApproxEqRel;
244244test gamma {
245245 inline for (&.{ f32, f64 }) |T| {
246246 const eps = @sqrt(std.math.floatEps(T));
247 try expectApproxEqRel(@as(T, 120), gamma(T, 6), eps);
248 try expectApproxEqRel(@as(T, 362880), gamma(T, 10), eps);
249 try expectApproxEqRel(@as(T, 6402373705728000), gamma(T, 19), eps);
247 try expectApproxEqRel(@as(T, 120.0), gamma(T, 6), eps);
248 try expectApproxEqRel(@as(T, 362880.0), gamma(T, 10), eps);
249 try expectApproxEqRel(@as(T, 6402373705728000.0), gamma(T, 19), eps);
250250
251251 try expectApproxEqRel(@as(T, 332.7590766955334570), gamma(T, 0.003), eps);
252252 try expectApproxEqRel(@as(T, 1.377260301981044573), gamma(T, 0.654), eps);
lib/std/math/modf.zig+1-1
......@@ -74,7 +74,7 @@ fn ModfTests(comptime T: type) type {
7474 r = modf(@as(T, 43874.3));
7575 try expectEqual(43874.0, r.ipart);
7676 // account for precision error
77 const expected_b: T = 43874.3 - @as(T, 43874);
77 const expected_b: T = 43874.3 - @as(T, 43874.0);
7878 try expectApproxEqAbs(expected_b, r.fpart, epsilon);
7979
8080 r = modf(@as(T, 1234.340780));
lib/std/math/pow.zig+2-2
......@@ -192,8 +192,8 @@ fn isOddInteger(x: f64) bool {
192192}
193193
194194test isOddInteger {
195 try expect(isOddInteger(math.maxInt(i64) * 2) == false);
196 try expect(isOddInteger(math.maxInt(i64) * 2 + 1) == false);
195 try expect(isOddInteger(@floatFromInt(math.maxInt(i64) * 2)) == false);
196 try expect(isOddInteger(@floatFromInt(math.maxInt(i64) * 2 + 1)) == false);
197197 try expect(isOddInteger(1 << 53) == false);
198198 try expect(isOddInteger(12.0) == false);
199199 try expect(isOddInteger(15.0) == true);
lib/std/zon/parse.zig+3-3
......@@ -2774,11 +2774,11 @@ test "std.zon parse float" {
27742774
27752775 // Test big integers
27762776 try std.testing.expectEqual(
2777 @as(f32, 36893488147419103231),
2777 @as(f32, 36893488147419103231.0),
27782778 try fromSlice(f32, gpa, "36893488147419103231", null, .{}),
27792779 );
27802780 try std.testing.expectEqual(
2781 @as(f32, -36893488147419103231),
2781 @as(f32, -36893488147419103231.0),
27822782 try fromSlice(f32, gpa, "-36893488147419103231", null, .{}),
27832783 );
27842784 try std.testing.expectEqual(@as(f128, 0x1ffffffffffffffff), try fromSlice(
......@@ -2788,7 +2788,7 @@ test "std.zon parse float" {
27882788 null,
27892789 .{},
27902790 ));
2791 try std.testing.expectEqual(@as(f32, 0x1ffffffffffffffff), try fromSlice(
2791 try std.testing.expectEqual(@as(f32, @floatFromInt(0x1ffffffffffffffff)), try fromSlice(
27922792 f32,
27932793 gpa,
27942794 "0x1ffffffffffffffff",