From 5ac9968021bf9d811c275d70bd3a75d7640caad9 Mon Sep 17 00:00:00 2001 From: adrien Date: Mon, 25 May 2026 13:53:17 +0200 Subject: [PATCH] Added back more test for TensorAlloc --- src/TensorAlloc.zig | 186 +++++++++++++++++++++++++++++++------------- 1 file changed, 132 insertions(+), 54 deletions(-) diff --git a/src/TensorAlloc.zig b/src/TensorAlloc.zig index 4a440bf..c996ac8 100644 --- a/src/TensorAlloc.zig +++ b/src/TensorAlloc.zig @@ -469,6 +469,60 @@ pub fn Tensor( pub fn neAll(self: *const Self, alloc: Allocator, other: anytype) !bool { return !(try self.eqAll(alloc, other)); } + + pub fn formatNumber( + self: *const Self, + writer: *std.Io.Writer, + options: std.fmt.Number, + ) !void { + if (comptime total == 1) { + switch (@typeInfo(T)) { + .float, .comptime_float => try writer.printFloat(self.data[0], options), + .int, .comptime_int => try writer.printInt(self.data[0], 10, .lower, .{ + .width = options.width, + .alignment = options.alignment, + .fill = options.fill, + .precision = options.precision, + }), + else => unreachable, + } + } else { + try writer.writeAll("("); + const max_to_print = 6; + inline for (0..@min(total, max_to_print)) |i| { + if (i > 0) try writer.writeAll(", "); + switch (@typeInfo(T)) { + .float, .comptime_float => try writer.printFloat(self.data[i], options), + .int, .comptime_int => try writer.printInt(self.data[i], 10, .lower, .{ + .width = options.width, + .alignment = options.alignment, + .fill = options.fill, + .precision = options.precision, + }), + else => unreachable, + } + if (comptime i == max_to_print - 1 and total != max_to_print - 1) + try writer.writeAll(", ..."); + } + try writer.writeAll(")"); + } + + var first = true; + inline for (std.enums.values(Dimension)) |bu| { + const v = dims.get(bu); + if (comptime v == 0) continue; + if (!first) try writer.writeAll("."); + first = false; + + const uscale = scales.get(bu); + if (bu == .T and (uscale == .min or uscale == .hour or uscale == .year)) + try writer.print("{s}", .{uscale.str()}) + else + try writer.print("{s}{s}", .{ uscale.str(), bu.unit() }); + + if (v != 1) try sh.printSuperscript(writer, v); + } + } }; } @@ -754,60 +808,84 @@ test "TensorAlloc | Scalar Conversion: hours -> minutes -> seconds" { try std.testing.expectEqual(3600, sec.data[0]); } -// test "TensorAlloc | Scalar Format" { -// const MeterPerSecondSq = Tensor(f32, .{ .L = 1, .T = -2 }, .{ .T = .n }, &.{1}); -// const Meter = Tensor(f32, .{ .L = 1 }, .{}, &.{1}); -// -// const m = Meter.splat(1.23456); -// const accel = MeterPerSecondSq.splat(9.81); -// -// var buf: [64]u8 = undefined; -// var res = try std.fmt.bufPrint(&buf, "{d:.2}", .{m}); -// try std.testing.expectEqualStrings("1.23m", res); -// -// res = try std.fmt.bufPrint(&buf, "{d}", .{accel}); -// try std.testing.expectEqualStrings("9.81m.ns⁻²", res); -// } -// -// test "TensorAlloc | Scalar Abs" { -// const Meter = Tensor(i128, .{ .L = 1 }, .{}, &.{1}); -// const MeterF = Tensor(f32, .{ .L = 1 }, .{}, &.{1}); -// -// try std.testing.expectEqual(50, Meter.splat(-50).abs().data[0]); -// try std.testing.expectEqual(42.5, MeterF.splat(-42.5).abs().data[0]); -// } -// -// test "TensorAlloc | Scalar Pow" { -// const Meter = Tensor(i128, .{ .L = 1 }, .{}, &.{1}); -// const d = Meter.splat(4); -// try std.testing.expectEqual(16, d.pow(2).data[0]); -// try std.testing.expectEqual(64, d.pow(3).data[0]); -// } -// -// test "TensorAlloc | Scalar add/sub bare number on dimensionless scalar" { -// const DimLess = Tensor(i128, .{}, .{}, &.{1}); -// const a = DimLess.splat(10); -// try std.testing.expectEqual(15, a.add(DimLess.splat(5)).data[0]); -// try std.testing.expectEqual(7, a.sub(DimLess.splat(3)).data[0]); -// } -// -// test "TensorAlloc | Scalar Imperial length scales" { -// const Foot = Tensor(f64, .{ .L = 1 }, .{ .L = .ft }, &.{1}); -// const Meter = Tensor(f64, .{ .L = 1 }, .{}, &.{1}); -// const Inch = Tensor(f64, .{ .L = 1 }, .{ .L = .inch }, &.{1}); -// -// try std.testing.expectApproxEqAbs(0.3048, Foot.splat(1.0).to(Meter).data[0], 1e-9); -// try std.testing.expectApproxEqAbs(1.0, Inch.splat(12.0).to(Foot).data[0], 1e-9); -// } -// -// test "TensorAlloc | Scalar Imperial mass scales" { -// const Pound = Tensor(f64, .{ .M = 1 }, .{ .M = .lb }, &.{1}); -// const Ounce = Tensor(f64, .{ .M = 1 }, .{ .M = .oz }, &.{1}); -// -// const total = Pound.splat(2.0).add(Ounce.splat(8.0)).to(Pound); -// try std.testing.expectApproxEqAbs(2.5, total.data[0], 1e-6); -// } -// +test "TensorAlloc | Scalar Format" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const MeterPerSecondSq = Tensor(f32, .{ .L = 1, .T = -2 }, .{ .T = .n }, &.{1}); + const Meter = Tensor(f32, .{ .L = 1 }, .{}, &.{1}); + + const m = try Meter.splat(alloc, 1.23456); + const accel = try MeterPerSecondSq.splat(alloc, 9.81); + + var buf: [64]u8 = undefined; + var res = try std.fmt.bufPrint(&buf, "{d:.2}", .{m}); + try std.testing.expectEqualStrings("1.23m", res); + + res = try std.fmt.bufPrint(&buf, "{d}", .{accel}); + try std.testing.expectEqualStrings("9.81m.ns⁻²", res); +} + +test "TensorAlloc | Scalar Abs" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const Meter = Tensor(i128, .{ .L = 1 }, .{}, &.{1}); + const MeterF = Tensor(f32, .{ .L = 1 }, .{}, &.{1}); + + try std.testing.expectEqual(50, (try (try Meter.splat(alloc, -50)).abs(alloc)).data[0]); + try std.testing.expectEqual(42.5, (try (try MeterF.splat(alloc, -42.5)).abs(alloc)).data[0]); +} + +test "TensorAlloc | Scalar Pow" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const Meter = Tensor(i128, .{ .L = 1 }, .{}, &.{1}); + const d = try Meter.splat(alloc, 4); + try std.testing.expectEqual(16, (try d.pow(alloc, 2)).data[0]); + try std.testing.expectEqual(64, (try d.pow(alloc, 3)).data[0]); +} + +test "TensorAlloc | Scalar add/sub bare number on dimensionless scalar" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const DimLess = Tensor(i128, .{}, .{}, &.{1}); + const a = try DimLess.splat(alloc, 10); + try std.testing.expectEqual(15, (try a.add(alloc, try DimLess.splat(alloc, 5))).data[0]); + try std.testing.expectEqual(7, (try a.sub(alloc, try DimLess.splat(alloc, 3))).data[0]); +} + +test "TensorAlloc | Scalar Imperial length scales" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const Foot = Tensor(f64, .{ .L = 1 }, .{ .L = .ft }, &.{1}); + const Meter = Tensor(f64, .{ .L = 1 }, .{}, &.{1}); + const Inch = Tensor(f64, .{ .L = 1 }, .{ .L = .inch }, &.{1}); + + try std.testing.expectApproxEqAbs(0.3048, (try (try Foot.splat(alloc, 1.0)).to(alloc, Meter)).data[0], 1e-9); + try std.testing.expectApproxEqAbs(1.0, (try (try Inch.splat(alloc, 12.0)).to(alloc, Foot)).data[0], 1e-9); +} + +test "TensorAlloc | Scalar Imperial mass scales" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + + const Pound = Tensor(f64, .{ .M = 1 }, .{ .M = .lb }, &.{1}); + const Ounce = Tensor(f64, .{ .M = 1 }, .{ .M = .oz }, &.{1}); + + const total = try (try (try Pound.splat(alloc, 2.0)).add(alloc, try Ounce.splat(alloc, 8.0))).to(alloc, Pound); + try std.testing.expectApproxEqAbs(2.5, total.data[0], 1e-6); +} + // // ─── Vector / Tensor tests ──────────────────────────────────────────────── // // test "TensorAlloc | Vector initiate" {