fixing phi management
Build / build (push) Successful in 39s
Test / build (push) Successful in 1m26s

This commit is contained in:
2026-07-03 14:45:13 +02:00
parent 4a8b24d676
commit 58cf66b6c9
4 changed files with 159 additions and 29 deletions
+9
View File
@@ -78,6 +78,9 @@ test "Maths primitives" {
.expected_outputs = &.{
std.mem.asBytes(&[_]T{ expected, expected, expected, expected }),
},
.expected_output_tolerances = if (@typeInfo(T) == .float) &.{
case.FloatTolerance.default(T),
} else &.{},
});
}
}
@@ -150,6 +153,9 @@ test "Maths vectors" {
.expected_outputs = &.{
std.mem.asBytes(&@as([L]T, expected)),
},
.expected_output_tolerances = if (@typeInfo(T) == .float) &.{
case.FloatTolerance.default(T),
} else &.{},
});
}
}
@@ -249,6 +255,9 @@ test "Maths vectors with scalars" {
.expected_outputs = &.{
std.mem.asBytes(&@as([L]T, expected)),
},
.expected_output_tolerances = if (@typeInfo(T) == .float) &.{
case.FloatTolerance.default(T),
} else &.{},
});
}
}
+57
View File
@@ -24,10 +24,37 @@ pub const case = struct {
source: []const u32,
inputs: []const []const u8 = &.{},
expected_outputs: []const []const u8 = &.{},
expected_output_tolerances: []const ?FloatTolerance = &.{},
descriptor_sets: []const []const []u8 = &.{},
expected_descriptor_sets: []const []const []const u8 = &.{},
};
const FloatKind = enum { f32, f64 };
pub const FloatTolerance = struct {
kind: FloatKind,
absolute: f64,
pub fn of(comptime T: type, absolute: f64) FloatTolerance {
return .{
.kind = switch (T) {
f32 => .f32,
f64 => .f64,
else => @compileError("FloatTolerance only supports f32 and f64"),
},
.absolute = absolute,
};
}
pub fn default(comptime T: type) FloatTolerance {
return of(T, switch (T) {
f32 => 1e-6,
f64 => 1e-12,
else => @compileError("FloatTolerance only supports f32 and f64"),
});
}
};
pub fn expect(config: Config) !void {
const allocator = std.testing.allocator;
@@ -66,6 +93,12 @@ pub const case = struct {
defer allocator.free(output);
try rt.readOutput(output[0..], module.output_locations[n][0]);
if (n < config.expected_output_tolerances.len) {
if (config.expected_output_tolerances[n]) |tolerance| {
try expectApproxBytes(expected, output, tolerance);
continue;
}
}
try std.testing.expectEqualSlices(u8, expected, output);
}
@@ -77,6 +110,30 @@ pub const case = struct {
}
}
fn expectApproxBytes(expected: []const u8, actual: []const u8, tolerance: FloatTolerance) !void {
try std.testing.expectEqual(expected.len, actual.len);
const stride: usize = switch (tolerance.kind) {
.f32 => @sizeOf(f32),
.f64 => @sizeOf(f64),
};
try std.testing.expectEqual(@as(usize, 0), expected.len % stride);
var i: usize = 0;
while (i < expected.len) : (i += stride) {
const expected_value = readFloat(expected[i .. i + stride], tolerance.kind);
const actual_value = readFloat(actual[i .. i + stride], tolerance.kind);
try std.testing.expectApproxEqAbs(expected_value, actual_value, tolerance.absolute);
}
}
fn readFloat(bytes: []const u8, kind: FloatKind) f64 {
return switch (kind) {
.f32 => @floatCast(@as(f32, @bitCast(std.mem.readInt(u32, bytes[0..@sizeOf(u32)], .little)))),
.f64 => @bitCast(std.mem.readInt(u64, bytes[0..@sizeOf(u64)], .little)),
};
}
pub fn random(comptime T: type) T {
var prng: std.Random.DefaultPrng = .init(@intCast(std.Io.Timestamp.now(std.testing.io, .real).toNanoseconds()));
const rand = prng.random();