Skip to content

A matrix compiles to a GenTensor over its elements' type, and the arithmetic on it to GenericTensor's operations - #1425

Merged
Rafael-SOWNet merged 3 commits into
masterfrom
compile-matrices
Sep 18, 2026
Merged

Rafael-SOWNet merged 3 commits into
masterfrom
compile-matrices

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

#526, per the comment there: "just run GenericTensor through our functions".

Under the LINQ compiler a Matrix node compiles to a GenTensor<T, TWrapper> over its elements' common type, filled element by element from the compiled elements, and a sum, difference, product, quotient or whole power with a matrix in it becomes the tensor operation of that name — PiecewiseAdd/PiecewiseSubtract, MatrixMultiply, the piecewise operations by a scalar (converted to the element type), MatrixPower. GenericTensor takes its element arithmetic from a struct and ships none for the numeric types, so DoubleOperations, SingleOperations, ComplexOperations, Int32Operations, Int64Operations, BigIntegerOperations are added in AngouriMath.Core.Compilation.IntoLinq; GenTensor<double, DoubleOperations> is the type to compile to and to pass a matrix in as, and TensorCompilation.TensorTypeOf(typeof(double)) names it.

"[[x, 2 x], [x + 1, x^2]]".ToEntity().Compile<double, GenTensor<double, DoubleOperations>>("x")(3)   // [[3, 6], [4, 9]]
"A * B".ToEntity().Compile<GenTensor<…>, GenTensor<…>, GenTensor<…>>("A", "B")                        // the matrix product
"2 A + B - 1", "x * [[1, 2], [3, 4]] / 2", "A ^ 3"                                                     // scale, shift, power

AOT. The methods the compiled tree calls are closed over each element type at compile time (Kit.For<double, DoubleOperations>() and five more) and named through expression trees, the way the protocol keeps its own MethodInfo tables: nothing generic is constructed at run time. The first draft used MakeGenericType/MakeGenericMethod/NewArrayInit and the trimming and NativeAOT analyzers refused it as errors (IL2060, IL3050 — #363's gate doing its job), so a matrix is built by Empty(rows, cols) and a chain of Set(tensor, index, value) calls instead.

Refusals, all UncompilableNodeException with a message that says so: a matrix asked for as a number, a number as a matrix, two matrices over different element types, and a function of a matrix (sin(A) was a KeyNotFoundException out of the type table). An expression of matrices with a scalar value still simplifies to the scalar first, as #425 made it ([[1, 0]] * [[a, b], [c, d]] * [[0], [1]] → 2 at (1, 2, 3, 4)).

MatrixCompilationTest's three "a matrix cannot be compiled" rows are rewritten as "cannot be compiled as a number", which is what they now test; CompileMatrixTest has the rows above. Exceptions.md and BREAKING-CHANGES.md updated ("Addition, not silent"). Full suite: 11851 passed, 0 failed after that rewrite. Not on the Simplify/evaluation path, so the benchmark gate is not concerned.

Closes #526.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 3 commits September 18, 2026 21:58
…thmetic on it to GenericTensor's operations

#526: "just run GenericTensor through our functions". Under the LINQ compiler a Matrix node is
a GenTensor<T, TWrapper> over the common type of its compiled elements, filled element by
element, and a sum, difference, product, quotient or whole power with a matrix in it is the
tensor operation of that name -- PiecewiseAdd, PiecewiseSubtract, MatrixMultiply, the
piecewise operations by a scalar converted to the element type, MatrixPower -- so that
"A * B" compiled over two tensors is the matrix product and "2 A + B - 1" scales, adds and
shifts. GenericTensor takes its element arithmetic from a struct and ships none for the
numeric types, so DoubleOperations, SingleOperations, ComplexOperations, Int32Operations,
Int64Operations and BigIntegerOperations are here, in AngouriMath.Core.Compilation.IntoLinq,
and GenTensor<double, DoubleOperations> is the type to compile to and to pass a matrix in as.

The methods the compiled tree calls are closed over each element type at compile time and
named through expression trees, the way the protocol keeps its own tables: nothing generic is
constructed at run time, which the trimming and NativeAOT analyzers refuse (#363). A matrix
as a number, a number as a matrix, and a function of a matrix are UncompilableNodeException
with a message that says so, where sin(A) was a KeyNotFoundException out of a type table.
An expression of matrices with a scalar value still simplifies to the scalar first, as #425
made it.

Closes #526.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
…enericTensor's expression-compiled ones, so the NativeAOT gate passes

The first push failed TrimmingAndAot on both platforms: GenTensor.PiecewiseAdd, MatrixMultiply
and the rest build and compile an expression tree for their loops, which ILC reports as IL3050
the moment they are reachable -- and Kit.For roots them for six element types. Add, Subtract,
Multiply, the scalar operations and Power are now loops over the wrapper's Add and Multiply, and
Power is by repeated squaring, refusing a negative exponent. GenTensor stays the container.
The smoke test compiles a matrix expression now, so the gate covers this path from here on.
Published natively and run locally: 45 checks, 0 failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet

Copy link
Copy Markdown
Member Author

The first push failed TrimmingAndAot on both platforms — GenTensor.PiecewiseAdd, MatrixMultiply and the rest build and compile an expression tree for their loops, and ILC reports that as IL3050 the moment they are reachable, which Kit.For made them for six element types. 075524da writes the arithmetic as plain loops over the wrapper's Add/Multiply (power by repeated squaring, a negative exponent refused) with GenTensor kept as the container, and adds a compiled-matrix check to the AOT smoke test so the gate covers this path from now on. Published natively and run locally: 45 checks, 0 failed. The PR description's "run GenericTensor through our functions" still holds for the type; the loops are what its operations compile to anyway.

@Rafael-SOWNet
Rafael-SOWNet merged commit afe7966 into master Sep 18, 2026
32 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the compile-matrices branch September 18, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compile matrices

1 participant