NDArray vs Matrix in NuMojo¶
NuMojo provides two primary array types: NDArray and Matrix.
Both are useful, but they serve slightly different purposes.
Quick rule of thumb¶
- Use
NDArraywhen your data can be 1D, 2D, 3D, or higher. - Use
Matrixwhen your data is always 2D and your workflow is primarily linear algebra.
What is NDArray?¶
NDArray is the general-purpose n-dimensional container in NuMojo.
Use it for:
- tensors and multi-axis scientific data
- flexible slicing/indexing across arbitrary dimensions
- routines that should work on any dimensionality
Typical examples:
- signal batches with shape
(batch, channels, time) - image stacks with shape
(n, h, w, c) - simulation grids with shape
(x, y, z)
What is Matrix?¶
Matrix is a dedicated 2D array type specialized for matrix workflows.
Use it for:
- classic linear algebra pipelines
- code where shape is always
(rows, cols) - APIs and methods designed around matrix semantics
Typical examples:
- solving
Ax = b - matrix factorizations
- 2D table-like numerical data
API style differences¶
Both types support many similar operations, but usage style can differ:
NDArrayoften appears in function-oriented routines:nm.sum(a, axis=...)nm.reshape(a, Shape(...))Matrixoften supports matrix-specific methods:A.inv()- matrix-oriented indexing patterns
NuMojo also provides top-level routines that work with both where applicable.
Performance guidance¶
Choose the type that matches your domain model first, then optimize.
- If your data is inherently n-dimensional, forcing it into
Matrixis usually a bad fit. - If your data is strictly 2D and linear-algebra-heavy,
Matrixis often clearer and may be more optimized for those operations.
Interoperability mindset¶
A practical approach in real projects:
- Keep core tensor data in
NDArray. - Convert/reshape to 2D where a matrix algorithm is needed.
- Convert back to
NDArraylayout as needed for downstream steps.
Example: choosing by intent¶
import numojo as nm
from numojo.prelude import *
fn main() raises:
# NDArray: general n-dimensional use
var tensor = nm.random.randn(Shape(4, 3, 2))
print("tensor ndim =", tensor.ndim)
# Matrix: dedicated 2D linear algebra use
var A = Matrix.rand(shape=(4, 4))
var B = Matrix.rand(shape=(4, 1))
var x = nm.solve(A, B)
print("solution shape =", x.shape)
Common mistakes¶
- Using
Matrixfor 3D/4D data pipelines. - Using
NDArrayfor purely 2D linear algebra code without a reason. - Mixing indexing styles inconsistently in one module.
Recommendation for new contributors¶
When adding a new feature:
- If algorithm is shape-agnostic and naturally n-dimensional, implement for
NDArrayfirst. - If algorithm is mathematically matrix-specific (decomposition, solver kernels), implement for
Matrixfirst. - If both are valid, factor shared internals and expose both cleanly.
This keeps NuMojo coherent for both users and maintainers.