Skip to content

Compile a function of a matrix argument as the function of each entry, and vectors as arrays - #2435

Open
Rafael-SOWNet wants to merge 1 commit into
masterfrom
feature/compiled-functions-of-a-matrix
Open

Rafael-SOWNet wants to merge 1 commit into
masterfrom
feature/compiled-functions-of-a-matrix

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Follows #2429 (#2422). A function of a matrix argument now compiles under the LINQ compiler, as evaluation has it, and a T[] passes at the delegate's boundary as a column vector.

What evaluation does, measured on master and on the 2.6.0 package, and so what compiling does now:

  • Entry by entry:
    • sin, cos, exp, ln, sgn, arcsin, conj, floor, !, gamma, 2^A and x^A.
    • Two-argument functions with a number or a matrix of the same shape: log(2, A), log(A, 3), max, min, mod, binomial, polygamma, lambertw, the falling and rising factorials, divisorsigma, gcd and lcm.
  • abs of a column or a row vector is its norm sqrt(sum |v_k|^2), as The norm of a vector with complex entries is NaN when evaluated and wrong when simplified #2423 makes it in evaluation. abs of any other matrix is entry by entry. A T[,] argument that turns out at the call to be a vector of more than one entry throws InvalidMatrixOperationException, because its value would be a number while the delegate returns a matrix. A 1×1 array passes.
  • A power with a matrix base is the matrix power for a whole exponent (Compile a matrix argument as an array, with its inverse and whole powers #2429). sqrt(A) and A^(1/2) stay unevaluated in evaluation, so compiled they throw at the call.
  • T[], for all six element types, is an n×1 column, as an argument and as a result. A result known not to be a column is refused at Compile.
  • Mixed expressions compile: A * sin(x) + B, A + [[1, 2], [3, 4]], sin(x) * [[…]] * A. Element types widen where the value does: whole numbers to double, and real values to complex in a complex matrix.
Input, compiled 2.6.0 now
sin(A), exp(A), abs(A), 2 ^ A, log(2, A), max(A, B) UncompilableNodeException entry by entry, as evaluation
double[] argument AngouriBugException or KeyNotFoundException a column vector

These rows are in BREAKING-CHANGES.md.

Still refused: A^B, comparisons of matrices, A = B, not A, and a matrix used as a number unless it is known to be 1×1. Matrix functions in the power-series sense, exp(A) as a series or A^(1/2), are computed neither by evaluation nor by compilation. Whether f(A) of a square matrix should mean the matrix function is a question for v3 (#1019).

Checked on this branch:

  • Tests: UnitTests 19454 passed, plus the MCP, Terminal, InteractiveWrapper and F# wrapper suites, and the AOT smoke test, which now has a check for a function of a matrix. Compiled values are checked against evaluation at real, negative and complex points, over double and Complex, for T[,], T[] and GenTensor arguments.
  • Harnesses: BoundCheck, RootCheck, CasBench, PropCheck, SimpSweep, RuleCheck, CanonCheck and Confluence all pass. limitcheck is not run, since nothing here touches limits.

🤖 Generated with Claude Code

…, and vectors as arrays

Evaluation applies a function to a matrix entry by entry: ExpandOnOneArgument maps a
one-argument function over it, and ExpandOnTwoArguments a two-argument one over a matrix and a
number or two matrices of one shape. Measured on master and on 2.6.0 for sin, cos, exp, ln,
sgn, conj, log, max, min, mod, binomial and a number to the power of a matrix. The exceptions
are a power with a matrix base, which is the matrix power and is left unevaluated where the
exponent is not whole (sqrt(A) included), and abs of a column vector, which is its norm. The
LINQ compiler refused all of these for a matrix argument. It now compiles each the same way:

- A function of one argument maps over the entries, through a lambda nested in the tree, and a
  listed function of two maps over a matrix and a number, or zips two matrices of one shape.
  The entry type widens where the function's value does, and a complex matrix keeps a real
  value as complex. A matrix of statements, as A < 0 is, is refused, and so are equality of
  two matrices and a matrix to the power of a matrix.
- abs of something known when compiling to be a vector, a column or a row, is its norm,
  sqrt(sum |v_k|^2), scaled against overflow, as #2423 makes evaluation take it over the
  complex numbers and for a row as for a column. abs of a two-dimensional array is entry by
  entry, and a column or a row of more than one entry throws InvalidMatrixOperationException
  at the call, its value being a number.
- A one-dimensional array of any of the six element types is a column vector, as an argument
  and as the result. A result known not to be a column is refused at Compile, otherwise at
  the call.
- Two matrices over different element types widen the narrower to the other's, as a number
  does, so a written matrix of whole numbers combines with a matrix argument whatever the
  constants are compiled as.

CompileMatrixTest's sin(A) refusal now asks for sin(A) as a number, which is still refused;
sin(A) as a matrix is what this change compiles.

Measured: every new test compares the compiled value with Substitute then Evaled, entry by
entry, over double and Complex at negative and non-real points; over double an entry
evaluation puts off the real line must be NaN. The norm of a row is checked against sqrt(sum
|v_k|^2) of the evaluated row, written out, as #2423 is not on this branch.
work/compilecheck's matrix-argument rows, with these functions added, all agree with
evaluation or throw where it has no answer. Compile, matrix and tensor tests: 1318 passed.
FSharpWrapperUnitTests, same filter: 60 passed. The NativeAOT smoke test with a map over
Complex[,] and a norm over double[] added: 76 of 76. The 2.6.0 values in BREAKING-CHANGES.md
are measured on the 2.6.0 package.

Part of #526.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.18519% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.87%. Comparing base (ff72b6f) to head (1835279).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...pilation/IntoLinq/TensorCompilation.Elementwise.cs 82.94% 21 Missing and 8 partials ⚠️
...unctions/Compilation/IntoLinq/TensorCompilation.cs 85.00% 1 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2435      +/-   ##
==========================================
+ Coverage   86.85%   86.87%   +0.02%     
==========================================
  Files         312      313       +1     
  Lines       69709    69928     +219     
  Branches    20378    20440      +62     
==========================================
+ Hits        60543    60750     +207     
- Misses       4923     4934      +11     
- Partials     4243     4244       +1     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.41% <85.18%> (+0.02%) ⬆️
fsharp 32.97% <ø> (ø)
interactive 39.81% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ctions/Compilation/IntoLinq/CompilationProtocol.cs 94.22% <100.00%> (+0.24%) ⬆️
...Functions/Compilation/IntoLinq/IntoLinqCompiler.cs 97.32% <100.00%> (+0.58%) ⬆️
...unctions/Compilation/IntoLinq/TensorCompilation.cs 76.22% <85.00%> (+3.34%) ⬆️
...pilation/IntoLinq/TensorCompilation.Elementwise.cs 82.94% <82.94%> (ø)

... and 12 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant