From 1d70b482dea611a4b99410bfb9f16fb09fd97193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Krzy=C5=BCanowski?= Date: Sat, 24 Aug 2024 15:30:52 +0200 Subject: [PATCH] Add Zig Matrix example --- zig-matrix/.gitignore | 2 + zig-matrix/build.zig | 26 ++++++++ zig-matrix/src/main.zig | 132 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 zig-matrix/.gitignore create mode 100644 zig-matrix/build.zig create mode 100644 zig-matrix/src/main.zig diff --git a/zig-matrix/.gitignore b/zig-matrix/.gitignore new file mode 100644 index 0000000..dca1103 --- /dev/null +++ b/zig-matrix/.gitignore @@ -0,0 +1,2 @@ +zig-out/ +.zig-cache/ diff --git a/zig-matrix/build.zig b/zig-matrix/build.zig new file mode 100644 index 0000000..84a8b90 --- /dev/null +++ b/zig-matrix/build.zig @@ -0,0 +1,26 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const exe = b.addExecutable(.{ + .name = "zig-matrix", + .root_source_file = b.path("src/main.zig"), + .target = b.host, + }); + + b.installArtifact(exe); + + const run_exe = b.addRunArtifact(exe); + const run_step = b.step("run", "Run the application"); + + run_step.dependOn(&run_exe.step); + + const unit_tests = b.addTest(.{ + .root_source_file = b.path("src/main.zig"), + .target = b.host, + }); + + const test_step = b.step("test", "Run unit tests"); + const run_unit_tests = b.addRunArtifact(unit_tests); + + test_step.dependOn(&run_unit_tests.step); +} diff --git a/zig-matrix/src/main.zig b/zig-matrix/src/main.zig new file mode 100644 index 0000000..5b11714 --- /dev/null +++ b/zig-matrix/src/main.zig @@ -0,0 +1,132 @@ +const std = @import("std"); + +const MatrixOpError = error{ + IncompatibleSizes, +}; + +const Matrix = struct { + allocator: std.mem.Allocator, + numbers: []i64, + dimensions: []const u64, + + pub fn init(allocator: std.mem.Allocator, dimensions: []const u64) !Matrix { + var size: u64 = 1; + + for (dimensions) |dim| { + size *= dim; + } + + return Matrix{ + .allocator = allocator, + .numbers = try allocator.alloc(i64, size), + .dimensions = dimensions, + }; + } + + pub fn fill(self: Matrix, number: i64) void { + var i: u64 = 0; + while (i < self.numbers.len) { + self.numbers[i] = number; + i += 1; + } + } + + pub fn add(self: Matrix, allocator: std.mem.Allocator, other: Matrix) !Matrix { + if (!std.mem.eql(u64, self.dimensions, other.dimensions)) { + 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; + } + + for (other.numbers, 0..) |num, idx| { + result.numbers[idx] += num; + } + + return result; + } + + pub fn sub(self: Matrix, allocator: std.mem.Allocator, other: Matrix) !Matrix { + if (!std.mem.eql(u64, self.dimensions, other.dimensions)) { + 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; + } + + for (other.numbers, 0..) |num, idx| { + result.numbers[idx] -= num; + } + + return result; + } + + pub fn deinit(self: Matrix) void { + self.allocator.free(self.numbers); + } +}; + +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", .{}); +} + +test "matrix init" { + const mat = try Matrix.init(std.testing.allocator, &[_]u64{ 5, 5 }); + defer mat.deinit(); + + try std.testing.expect(mat.numbers.len == 25); +} + +test "matrix fill" { + const mat = try Matrix.init(std.testing.allocator, &[_]u64{ 5, 5 }); + defer mat.deinit(); + mat.fill(123); + + for (mat.numbers) |num| { + try std.testing.expect(num == 123); + } +} + +test "matrix add" { + const mat1 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + defer mat1.deinit(); + const mat2 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + defer mat2.deinit(); + + mat1.fill(1); + mat2.fill(2); + + const mat3 = try mat1.add(std.testing.allocator, mat2); + defer mat3.deinit(); + + try std.testing.expect(mat3.numbers[0] == 3); + try std.testing.expect(mat3.numbers[1] == 3); + try std.testing.expect(mat3.numbers[2] == 3); + try std.testing.expect(mat3.numbers[3] == 3); +} + +test "matrix sub" { + const mat1 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + defer mat1.deinit(); + const mat2 = try Matrix.init(std.testing.allocator, &[_]u64{ 2, 2 }); + defer mat2.deinit(); + + mat1.fill(1); + mat2.fill(2); + + const mat3 = try mat1.sub(std.testing.allocator, mat2); + defer mat3.deinit(); + + try std.testing.expect(mat3.numbers[0] == -1); + try std.testing.expect(mat3.numbers[1] == -1); + try std.testing.expect(mat3.numbers[2] == -1); + try std.testing.expect(mat3.numbers[3] == -1); +}