Matrices
Sun provides N-dimensional matrices through the standard library Matrix<T> class. Matrices support bracket indexing syntax and are backed by contiguous heap memory.
Importing the Standard Library
import "build/stdlib.moon";Creating Matrices
Use Matrix<T>(allocator, shape) to create a matrix with the specified dimensions:
function main() i32 {
var allocator = make_heap_allocator();
// 1D array (vector) of 10 elements
var v = Matrix<i32>(allocator, [10]);
// 2D matrix (3x4)
var m = Matrix<i32>(allocator, [3, 4]);
// 3D tensor (2x3x4)
var t = Matrix<f64>(allocator, [2, 3, 4]);
return 0;
}Indexing
Access elements using comma-separated indices in brackets:
function main() i32 {
var allocator = make_heap_allocator();
var m = Matrix<i32>(allocator, [3, 3]);
// Assignment
m[0, 0] = 1;
m[1, 1] = 5;
m[2, 2] = 9;
// Reading
var diag = m[0, 0] + m[1, 1] + m[2, 2]; // 15
return diag;
}For 1D matrices:
function main() i32 {
var allocator = make_heap_allocator();
var arr = Matrix<i32>(allocator, [5]);
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
return arr[0] + arr[1] + arr[2]; // 60
}Matrix Methods
get(indices) / set(indices, value)
Direct method access (equivalent to bracket syntax):
var val = m.get([i, j]); // Same as m[i, j]
m.set([i, j], value); // Same as m[i, j] = valueshape()
Returns the dimensions of the matrix:
function main() i64 {
var allocator = make_heap_allocator();
var m = Matrix<i32>(allocator, [3, 4]);
var s = m.shape();
println_i64(s[0]); // 3
println_i64(s[1]); // 4
return s[0];
}size()
Returns the total number of elements:
function main() i64 {
var allocator = make_heap_allocator();
var m = Matrix<i32>(allocator, [3, 4]);
return m.size(); // 12
}ndims()
Returns the number of dimensions:
function main() i64 {
var allocator = make_heap_allocator();
var t = Matrix<f32>(allocator, [2, 3, 4]);
return t.ndims(); // 3
}Matrix Views
MatrixView<T> provides a non-owning view into a Matrix<T> or another view. Views share memory with the original matrix.
Creating Views
Views are created via slicing or explicitly:
function main() i32 {
var allocator = make_heap_allocator();
var m = Matrix<i32>(allocator, [3, 3]);
// Fill matrix
m[0, 0] = 1; m[0, 1] = 2; m[0, 2] = 3;
m[1, 0] = 4; m[1, 1] = 5; m[1, 2] = 6;
m[2, 0] = 7; m[2, 1] = 8; m[2, 2] = 9;
// Create view (shares memory with m)
var view = MatrixView<i32>(m);
return view[1, 1]; // 5
}Views do not own their data. The original matrix must remain valid while the view is in use.
How Operator Overloading Works
When you write m[i, j], the compiler translates it to method calls:
| Syntax | Compiler Translation |
|---|---|
m[i, j] (read) | m.__index__([i, j]) |
m[i, j] = v (write) | m.__setindex__([i, j], v) |
To make your own class indexable, implement __index__ and __setindex__:
class MyArray {
var data: ptr<i32>;
var len: i64;
function init(allocator: ref HeapAllocator, size: i64) {
this.data = allocator.alloc<i32>(size);
this.len = size;
}
// Called for arr[i]
function __index__(indices: ref array<i64>) i32 {
return _load<i32>(this.data, indices[0]);
}
// Called for arr[i] = value
function __setindex__(indices: ref array<i64>, value: i32) void {
_store<i32>(this.data, indices[0], value);
}
}
function main() i32 {
var allocator = make_heap_allocator();
var arr = MyArray(allocator, 10);
arr[0] = 42; // Calls __setindex__
return arr[0]; // Calls __index__, returns 42
}Complete Example
import "build/stdlib.moon";
function main() i32 {
var allocator = make_heap_allocator();
// Create a 3x3 identity matrix
var identity = Matrix<i32>(allocator, [3, 3]);
// Initialize to zero
for (var i: i64 = 0; i < 3; i = i + 1) {
for (var j: i64 = 0; j < 3; j = j + 1) {
identity[i, j] = 0;
}
}
// Set diagonal to 1
identity[0, 0] = 1;
identity[1, 1] = 1;
identity[2, 2] = 1;
// Sum the diagonal
var trace = identity[0, 0] + identity[1, 1] + identity[2, 2];
return trace; // 3
}Memory Management
Matrix<T> uses an owning pointer (ptr<T>) for its data, which is automatically freed when the matrix goes out of scope. The allocator is only used during construction.
function createMatrix() i32 {
var allocator = make_heap_allocator();
var m = Matrix<i32>(allocator, [100, 100]);
m[50, 50] = 42;
return m[50, 50];
// m is automatically freed here
}