Relevant posts:
Decimo: v0.10.0, v0.9.0, v0.8.0, v0.7.0, v0.6.0, v0.2, first release
ArgMojo: v0.5.0, first release
Mojo Miji: update for Mojo v0.26.1, introduction
Hi Mojicians,
Mojo v1.0.0 finally landed (Horray!), and I have spent the last few weeks getting everything I maintain onto it. Four things to share:
- A new library, Linamo, linear algebra for Mojo specialised for two-dimensional matrices, reaches its first release, v0.1.0. It is now on the modular-community channel, so
pixi add linamois all it takes. Since NuMojo removed itsMatrixtype in its last release, Linamo fills the gap for 2D matrix operations. - Decimo v0.14.0 is the biggest release the library has had: a rebuilt integer core that is two to three times faster, trigonometry and IEEE 754 interchange on
Decimal128, many fixes. And it is now a Python package as well!, sopip install decimogets you a nearly drop-indecimalwritten in Mojo. - ArgMojo v0.8.0 is on Mojo v1.0.0 too, with
pixi add argmojo. - Mojo Miji, the online book I have been writing, is fully updated to Mojo v1.0.0 — and its code blocks are now runnable and editable in the browser.
All Mojo packages now live on the modular-community channel on prefix.dev, for linux-64, linux-aarch64 and osx-arm64. No git submodule, no vendored source, no build step:
pixi add linamo # brings decimo along as a dependency
pixi add decimo
pixi add argmojo
Most of this post is about Linamo, since it is the new one, followed by what changed in Decimo.
Linamo — linear algebra for Mojo
Linamo lives under the mojomath organisation. The name is LINear + Algebra + MOjo; it also reads as lin-amo, and amo is Latin for “I love”, so: “I love linear algebra”.
It is deliberately 2D only. If you want N-dimensional arrays, reach for NuMojo — that is a different and larger job. Linamo trades generality for a small API and matrix-specific kernels, closer in spirit to scipy.linalg or nalgebra than to NumPy.
There are three types, and one import:
| Type | What it is |
|---|---|
Matrix |
an owning 2-D matrix |
MatrixView |
a non-owning view, with strides |
StaticMatrix |
a matrix with a compile-time shape |
import linamo as la is the only import a program needs — every type and routine is re-exported, so la.<name> is the only spelling.
Views are read-only by default
This is the one design decision worth explaining, because it is the part that is not guessable from NumPy (and its former matmojo design used a different approach).
Slicing gives you a MatrixView: no copy, strides preserved, so a row, a column, a block or a transpose all cost nothing. But those views are immutable. Writing goes through a separate mutation module and dedicated methods, e.g., view_mut, rows_mut, cols_mut, fill, assign, store, which is the library’s only source of a mutable view.
The reason is that two read-only views of one matrix compose safely, so a[0:1, :] - a[1:2, :] is expressible, whereas a library where every slice is potentially mutable has to choose between rejecting that and allowing silent aliasing bugs. Making the write path explicit and rare felt like the better trade for a matrix library.
The element type is a type, not a DType
A Matrix is parameterised on an element type rather than a DType. This is closer to the built-in List instead of the numojo.NDArray. Initially Matrix also has the syntax Matrix[dtype.Float64] but finally I decided to drop it in favor of Matrix[Float64]. One reason is that dtype.Float64 looks really verbose to me. Another reason will become immediately clear to you when you read the following code example:
import linamo as la
var a = la.matrix[Float64]([[1, 2], [3, 4]]) # SIMD kernels, hardware speed
var b = la.matrix[la.BInt]([[1, 2], [3, 4]]) # arbitrary-precision integer
var c = la.matrix[la.Decimal]([[1, 2], [3, 4]]) # base-ten exact decimal
Same operators, same routines, same names — only the arithmetic underneath differs. The exact types come from Decimo and are re-exported by Linamo, so using one costs no second import.
This is possible because Decimo introduced the Numeric and Parsable traits (zero(), one(), -x, +, -, *, /, and from_string()). A matrix library asking for T: Numeric was in fact the motivating case for adding them.
BInt has no width to overflow, so a product simply keeps every digit:

** climbs by repeated squaring, so fib**250 is a handful of matrix products rather than 250 of them (I am really a fan of Fabonacci numbers and I use it as examples everywhere :D, also the Miji ).
And the exactness is not only about tidier output. Consider a matrix that is exactly singular, because 0.1*0.6 - 0.2*0.3 is exactly zero:

In Float64 the determinant misses zero by one rounding step, inv believes it, and what comes back has entries around 5e17 — with nothing raised and nothing warned. The same elimination over Decimal reaches zero exactly and stops.
One honest caveat: the routines that run elimination (lu, det, solve, inv, lstsq) divide, so they mean whatever / means on the element type. Over Decimal that is a quotient at the type’s precision. Over BInt it truncates, and elimination then returns whole numbers that are not the answer, without raising. A decimal element type is what those routines are for, and the manual says so in bold.
What is in v0.1.0
- Creation:
matrix,zeros,ones,full,eye,identity,diag,arange,linspace, the*_likeforms,from_string,rand/seed. - Operators:
+,-, unary-element-wise;*and@are both the matrix product;**is repeated multiplication andA**-1inverts. The element-wise product, quotient and power have no symbol left, so they are themul,div,powmethods. Scalars, reflected operands and in-place forms throughout. - Comparison and logic: comparisons return a
bool_mask;isclose/allclose, thelogical_*family,all/any, and ascalar_*form of each. - Linear algebra:
transpose,trace,lu(PA = LU),cholesky,qr,det,solve,inv,matrix_power,lstsq.matmuldispatches over four SIMD paths according to the contiguity of its operands. - Shape, reductions, sorting:
reshape,resize,flatten,contiguous,broadcast_to,astype;sum,cumsum,prod,min,max,argmin,argmax,sort,argsort; plusfoldandapply_along_axisfor anything the library does not name itself. - NumPy interop:
from_numpy/to_numpy. - Every type prints through one aligned grid that shows the element type, the shape, and the strides when they are not the dense ones. Large matrices elide rows and columns; long fractions are trimmed and marked (like numpy).
pixi add linamo
The User Manual is the full tour. It starts with the two types and their mutability model, since that is the part NumPy does not prepare you for.
Decimo v0.14.0 — and pip install decimo
Decimo is the arbitrary-precision integer and decimal library that Linamo’s exact element types come from: BigInt / BInt for integers of any size, BigDecimal / BDec for exact base-ten decimals, Decimal128 for sixteen-byte fixed-point money, BigFloat on MPFR, and Rational. It is on the channel too:
pixi add decimo

v0.14.0 is the largest release so far. Three parts of it are worth calling out.
It is now a Python package (Horray!)
Decimo compiles to a CPython extension, and there are wheels:
pip install decimo
CPython 3.13 and 3.14, on macOS arm64 and Linux x86_64 / arm64, with the Mojo runtime bundled — nothing else to install. What you get is a near drop-in for the standard library’s decimal and a superset of it: the whole decimal.Decimal surface including the Decimal((sign, digits, exponent)) constructor, every rounding mode but ROUND_05UP, and then the things decimal has no equivalent of — pi() and e() to any precision, correctly-rounded transcendentals, and Decimal128 with trigonometry. The test suite checks every operation against the standard library’s answer.
On speed, the honest summary: faster once the numbers are large, and 20–25% behind libmpdec on small ones. At a thousand digits Decimal(1) / Decimal(7) is about 2.9× quicker; at a million digits pi() is nearly twelve times quicker than pure-Python mpmath; BigInt multiplication runs about fifteen times quicker than CPython’s int. Conversions no longer route through a string, which is a 2–15× saving on its own.
The integer core was rebuilt
BigUInt moved from base 10^9 to base 10^18 and BigInt from base 2^32 to base 2^64, both gained a number-theoretic transform for very large operands, and small values are now stored inline instead of on the heap. Addition and subtraction are 2–3× faster, multiplication 2–3×, division 1.2–2×. BigInt.sqrt() uses Zimmermann’s recursion and is 1.8× faster above ten thousand digits. Heap blocks are reused rather than freed, which roughly doubles the speed of small operations, and BigDecimal.pi() is four orders of magnitude faster on a reworked Chudnovsky.
Correct digits, not probably-correct digits
Decimal128 gains the trigonometric functions (sin, cos, tan, cot, sec, csc) with proper argument reduction, and IEEE 754 decimal128 interchange through to_ieee754() / from_ieee754().
More importantly, the transcendentals no longer assume a fixed number of guard digits (this is a quick but dirty way to ensure correctness in the previous versions, safe when the precision is low and risky when it is high): they check the entire rounding interval before committing to a last digit, and budget_for() sizes the argument reduction by how close the input sits to a multiple of π/2. That closed a genuinely bad class of bug — sin, cos and tan were silently wrong for large arguments such as 10^150. If you are on 0.13.0 or earlier, please upgrade.
The CLI calculator is still the quickest way to feel what arbitrary precision buys you — ans, a : settings system, and settings you can apply inline to a single expression. It has a Homebrew tap now:
brew install forfudan/tap/decimo

Two notes if you are upgrading a Mojo project. BigUInt.words and BigInt.words are List[UInt64] now (there is a BigUInt.Word alias to spell that with), BInt(raw_words=..., sign=...) takes a Magnitude, the Integer alias is gone in favour of BInt / BigInt, and from_float() is deprecated in favour of from_float_scalar(). Values and results are unchanged; only code that touched those names needs an edit.
That last rename is why Linamo v0.1.0 pins decimo >=0.13,<0.14: it re-exports Integer. pixi add linamo therefore resolves Decimo 0.13.x for you, and Linamo’s next release moves the pin to 0.14. These are mainly private APIs, so I hope that you will never feel the impact of the changes.
Also worth remembering from v0.13.0, since it is what Linamo is built on: the Numeric, Parsable and Rootable traits let code be written once and run over BigInt, BigUInt, BigDecimal, Decimal128 and BigFloat alike.
ArgMojo v0.8.0 — on Mojo v1.0.0
ArgMojo v0.8.0 brings the CLI argument parser — both the builder API and the struct-based declarative API — onto Mojo v1.0.0.
pixi add argmojo
The declarative side is the part I would point a newcomer at: the struct declares the constraints, and the parser enforces them for you.

Shell completion:

Mojo Miji — fully on v1.0.0, and now interactive
Mojo Miji — A Guide to Mojo Programming Language from a Pythonista’s Perspective is now completely updated to Mojo v1.0.0. Seven parts, from pixi init through the ownership system to a matrix library built by hand (i.e., matmojo, the initial shape of linamo).
The bigger change is that the Mojo code blocks on the page are now runnable and editable (thanks to the Mojo team for opening a door). There is a Run button at the right end of each block’s header line; click it and the output appears underneath a few seconds later. Click into the code, change a line, run it again. No local toolchain, no switching windows. For a book whose whole premise is “here is how this differs from Python”, being able to poke at the difference where you are reading about it makes a real difference to how it reads, and it means the very first chapter can show you Mojo running before it asks you to install anything.
That figure is the very first program in the book, run from the page it is explained on.
Feedback and issues are very welcome, on any of the four. Happy hacking! ![]()


