From 30cc0d98c6930c6f09879a42d45a596aa8138ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Krzy=C5=BCanowski?= Date: Sat, 24 Aug 2024 18:15:22 +0200 Subject: [PATCH] Add get/set to Zig Matrix example --- zig-matrix/src/main.zig | 121 +++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 21 deletions(-) diff --git a/zig-matrix/src/main.zig b/zig-matrix/src/main.zig index 5b11714..a90bf12 100644 --- a/zig-matrix/src/main.zig +++ b/zig-matrix/src/main.zig @@ -2,6 +2,7 @@ const std = @import("std"); const MatrixOpError = error{ IncompatibleSizes, + OutOfBounds, }; const Matrix = struct { @@ -9,20 +10,58 @@ const Matrix = struct { numbers: []i64, dimensions: []const u64, - pub fn init(allocator: std.mem.Allocator, dimensions: []const u64) !Matrix { + pub fn init(allocator: std.mem.Allocator, dimensions: []const u64, init_numbers: []const i64) !Matrix { var size: u64 = 1; for (dimensions) |dim| { size *= dim; } + var numbers = try allocator.alloc(i64, size); + + for (0.., init_numbers) |i, num| { + numbers[i] = num; + } + return Matrix{ .allocator = allocator, - .numbers = try allocator.alloc(i64, size), + .numbers = numbers, .dimensions = dimensions, }; } + fn position_deep_to_flat(self: Matrix, position: []const u64) u64 { + var flat_position: u64 = 0; + var curr_volume: u64 = 1; + + for (0.., position) |i, pos| { + flat_position += pos * curr_volume; + curr_volume *= self.dimensions[i]; + } + + return flat_position; + } + + pub fn get(self: Matrix, position: []const u64) !i64 { + const flat_position = position_deep_to_flat(self, position); + + if (flat_position >= self.numbers.len) { + return error.OutOfBounds; + } + + return self.numbers[flat_position]; + } + + pub fn set(self: Matrix, position: []const u64, value: i64) !void { + const flat_position = position_deep_to_flat(self, position); + + if (flat_position >= self.numbers.len) { + return error.OutOfBounds; + } + + self.numbers[flat_position] = value; + } + pub fn fill(self: Matrix, number: i64) void { var i: u64 = 0; while (i < self.numbers.len) { @@ -36,12 +75,11 @@ const Matrix = struct { return error.IncompatibleSizes; } - var result: Matrix = try Matrix.init(allocator, self.dimensions); - result.fill(0); - - for (self.numbers, 0..) |num, idx| { - result.numbers[idx] += num; - } + var result: Matrix = try Matrix.init( + allocator, + self.dimensions, + self.numbers, + ); for (other.numbers, 0..) |num, idx| { result.numbers[idx] += num; @@ -55,12 +93,11 @@ const Matrix = struct { return error.IncompatibleSizes; } - var result: Matrix = try Matrix.init(allocator, self.dimensions); - result.fill(0); - - for (self.numbers, 0..) |num, idx| { - result.numbers[idx] += num; - } + var result: Matrix = try Matrix.init( + allocator, + self.dimensions, + self.numbers, + ); for (other.numbers, 0..) |num, idx| { result.numbers[idx] -= num; @@ -75,18 +112,60 @@ const Matrix = struct { }; pub fn main() void { - std.debug.print("Please use 'zig build test --summary all' to run tests. This example does not have any other runnable code.\n", .{}); + const help_text = + \\Please use 'zig build test --summary all' to run tests. + \\This example does not have any other runnable code.\n" + ; + + std.debug.print(help_text, .{}); } test "matrix init" { - const mat = try Matrix.init(std.testing.allocator, &[_]u64{ 5, 5 }); + const mat = try Matrix.init(std.testing.allocator, &.{ 5, 5 }, &.{}); defer mat.deinit(); try std.testing.expect(mat.numbers.len == 25); } +test "matrix get 2 dim" { + const mat = try Matrix.init( + std.testing.allocator, + &.{ 3, 3 }, + &.{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + ); + defer mat.deinit(); + + try std.testing.expect(try mat.get(&.{ 0, 0 }) == 1); + try std.testing.expect(try mat.get(&.{ 1, 0 }) == 2); + try std.testing.expect(try mat.get(&.{ 2, 0 }) == 3); + try std.testing.expect(try mat.get(&.{ 0, 1 }) == 4); + try std.testing.expect(try mat.get(&.{ 1, 1 }) == 5); + try std.testing.expect(try mat.get(&.{ 2, 1 }) == 6); + try std.testing.expect(try mat.get(&.{ 0, 2 }) == 7); + try std.testing.expect(try mat.get(&.{ 1, 2 }) == 8); + try std.testing.expect(try mat.get(&.{ 2, 2 }) == 9); +} + +test "matrix get 3 dim" { + const mat = try Matrix.init( + std.testing.allocator, + &.{ 2, 2, 2 }, + &.{ 1, 2, 3, 4, 5, 6, 7, 8 }, + ); + defer mat.deinit(); + + try std.testing.expect(try mat.get(&.{ 0, 0, 0 }) == 1); + try std.testing.expect(try mat.get(&.{ 1, 0, 0 }) == 2); + try std.testing.expect(try mat.get(&.{ 0, 1, 0 }) == 3); + try std.testing.expect(try mat.get(&.{ 1, 1, 0 }) == 4); + try std.testing.expect(try mat.get(&.{ 0, 0, 1 }) == 5); + try std.testing.expect(try mat.get(&.{ 1, 0, 1 }) == 6); + try std.testing.expect(try mat.get(&.{ 0, 1, 1 }) == 7); + try std.testing.expect(try mat.get(&.{ 1, 1, 1 }) == 8); +} + test "matrix fill" { - const mat = try Matrix.init(std.testing.allocator, &[_]u64{ 5, 5 }); + const mat = try Matrix.init(std.testing.allocator, &.{ 5, 5 }, &.{}); defer mat.deinit(); mat.fill(123); @@ -96,9 +175,9 @@ test "matrix fill" { } test "matrix add" { - const mat1 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + const mat1 = try Matrix.init(std.testing.allocator, &.{ 2, 2 }, &.{}); defer mat1.deinit(); - const mat2 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + const mat2 = try Matrix.init(std.testing.allocator, &.{ 2, 2 }, &.{}); defer mat2.deinit(); mat1.fill(1); @@ -114,9 +193,9 @@ test "matrix add" { } test "matrix sub" { - const mat1 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + const mat1 = try Matrix.init(std.testing.allocator, &.{ 2, 2 }, &.{}); defer mat1.deinit(); - const mat2 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + const mat2 = try Matrix.init(std.testing.allocator, &.{ 2, 2 }, &.{}); defer mat2.deinit(); mat1.fill(1);