NdArray<T> stores a dense numerical array with a shape. Use it for matrices, images, tensors, and other data where dimensions matter. Use an ordinary [T] array when you need a growable list or rows of different lengths.
Construct arrays
use std.ndarray
let zeros = ndarray.zeros<f32>([2, 3])
let ones = ndarray.ones<i16>([4])
let filled = ndarray.full<float>([2, 2], 1.5)
let sequence = ndarray.arange(0, 10, 2)
let points = ndarray.linspace(0.0, 1.0, 5)
let matrix = ndarray.from_array<i32>(
[1, 2, 3, 4, 5, 6],
[2, 3],
)?from_array returns an error when the shape does not match the number of values. from_nested accepts rectangular nested arrays and rejects ragged rows.
Supported element types are bool, fixed-width signed and unsigned integers, f32, and float. Use astype<U>() for an explicit checked conversion.
Shape and indexing
println(matrix.rank()) // 2
println(matrix.shape()) // [2, 3]
println(matrix.strides()) // [3, 1]
println(matrix.get([1, -1])) // 6
matrix.set([0, 1], 20)Negative indexes count from the end of a dimension. get_or_none is useful when an out-of-bounds coordinate should be handled as none.
Views
Transpose, slice, axis swapping, squeezing, expanding, and broadcasting create views of the same values:
let transposed = matrix.transpose([1, 0])?
let row = matrix.slice([0, 0], [1, 3], [1, 1])?A write through the original array is visible through a writable view. A broadcast view is read-only because several coordinates may refer to the same value. Call copy() when you need independent writable data, or contiguous() when an API requires a compact row-major layout.
reshape reuses a contiguous array when possible and otherwise returns a compact copy.
Broadcasting and arithmetic
Binary operations align dimensions from the right. Equal dimensions match and a dimension of length one expands:
let row = ndarray.full<i32>([1, 3], 10)
let result = matrix + row
println(result.shape()) // [2, 3]Mixed integer arrays use a wide enough integer type. Operations involving float produce float; f32 + f32 remains f32. Boolean arithmetic is not allowed.
Use eq_elements for element-by-element equality, array_equal for exact shape and content equality, and all_close for approximate numeric equality.
Reductions and linear algebra
println(matrix.sum())
println(matrix.mean())
println(matrix.sum_axis(1).to_array())
let right = ndarray.from_array<i32>(
[1, 2, 3, 4, 5, 6],
[3, 2],
)?
println(ndarray.matmul(matrix, right)?.shape()) // [2, 2]sum, product, min, max, mean, any, and all reduce a whole array. The _axis forms preserve the other dimensions. dot accepts vectors; matmul handles vectors, matrices, and batched matrices.
Empty sums and products use their usual identities. Empty min, max, and mean return none; an invalid axis or incompatible matrix shape returns an error.
Raw bytes
Use to_bytes and from_bytes when exchanging a full array with an image, audio, or C API:
let data = ndarray.to_bytes(matrix)
let restored = ndarray.from_bytes<i32>(data, [2, 3])?The bytes use the host's byte order and are intended for local bulk transfer, not as a portable file format. to_bytes returns values in logical row-major order even when the input is a transposed or sliced view.
Iterate and discover
iter() yields values in logical row-major order and works with ordinary iterator methods:
let positive = matrix.iter().filter(|value| value > 0).count()Browse the complete surface with:
moon doc std ndarray
moon doc builtin NdArrayThe same signatures are available in the NdArray API reference.