From 97811cd4ccc753444e347d8b41e4c34ba3314891 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 23 Mar 2026 13:17:42 -0400 Subject: [PATCH 1/3] add algorithm section in the docs --- docs/make.jl | 1 + docs/src/index.md | 1 + docs/src/user_interface/algorithms.md | 143 ++++++++++++++++++++++ docs/src/user_interface/decompositions.md | 57 +-------- 4 files changed, 150 insertions(+), 52 deletions(-) create mode 100644 docs/src/user_interface/algorithms.md diff --git a/docs/make.jl b/docs/make.jl index 4584ff1c3..a92d1d8b0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -51,6 +51,7 @@ makedocs(; "User Interface" => [ "user_interface/compositions.md", "user_interface/decompositions.md", + "user_interface/algorithms.md", "user_interface/truncations.md", "user_interface/properties.md", "user_interface/matrix_functions.md", diff --git a/docs/src/index.md b/docs/src/index.md index 7055ba3ec..d5e298529 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -26,6 +26,7 @@ These operations typically follow some common skeleton, and here we go into a li ```@contents Pages = ["user_interface/compositions.md", "user_interface/decompositions.md", + "user_interface/algorithms.md", "user_interface/truncations.md", "user_interface/properties.md", "user_interface/matrix_functions.md"] Depth = 2 diff --git a/docs/src/user_interface/algorithms.md b/docs/src/user_interface/algorithms.md new file mode 100644 index 000000000..c05bc11b4 --- /dev/null +++ b/docs/src/user_interface/algorithms.md @@ -0,0 +1,143 @@ +```@meta +CurrentModule = MatrixAlgebraKit +CollapsedDocStrings = true +``` + +# [Algorithm Selection](@id sec_algorithmselection) + +All factorization functions in MatrixAlgebraKit accept an optional `alg` keyword argument that controls which algorithm is used and how it is configured. +By default, an appropriate algorithm is selected automatically based on the function and the array type. +This page explains how to override that default, what algorithm types are available, and how to configure them. + +## The `alg` Keyword + +The `alg` keyword is interpreted by [`MatrixAlgebraKit.select_algorithm`](@ref), which accepts five forms, e.g.: + +```julia +# Form 1: No alg — algorithm selected automatically based on function and array type. +Q, R = qr_compact(A); + +# Form 2: Symbol — creates Algorithm{:Householder}(; positive=false). +Q, R = qr_compact(A; alg = :Householder, positive = false); + +# Form 3: Algorithm type — calls Householder(; positive=false). +Q, R = qr_compact(A; alg = Householder, positive = false); + +# Form 4: Algorithm instance — used as-is; no additional kwargs are allowed. +Q, R = qr_compact(A; alg = Householder(; positive = false)); + +# Form 5: NamedTuple — equivalent to qr_compact(A; positive=false). +Q, R = qr_compact(A; alg = (; positive = false)); +``` + +!!! note + When passing an already-constructed algorithm instance (form 4), additional keyword arguments at the call site are not permitted and will throw an `ArgumentError`. + All configuration must go into the constructor in that case. + +```@docs; canonical=false +MatrixAlgebraKit.select_algorithm +``` + +## Discovering the Default Algorithm + +To check which algorithm is used by default for a given function and array type, call [`MatrixAlgebraKit.default_algorithm`](@ref). +The available keyword arguments depend on the algorithm type; refer to the docstrings listed in [Available Algorithm Types](@ref) below. + +```@docs; canonical=false +MatrixAlgebraKit.default_algorithm +``` + +## Configuring Algorithms + +Each algorithm accepts keyword arguments that control its behavior. +These can be provided either at the call site (forms 1–3) or inside the algorithm constructor: + +```julia +# The following four calls are all equivalent: +U, S, Vᴴ = svd_compact(A; fixgauge = false) +U, S, Vᴴ = svd_compact(A; alg = :SafeDivideAndConquer, fixgauge = false) +U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer, fixgauge = false) +U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer(; fixgauge = false)) +``` + +## The `DefaultAlgorithm` Sentinel + +Package developers who want to store algorithm configuration without committing to a specific algorithm can use `DefaultAlgorithm`. +It defers algorithm selection to call time, forwarding its stored keyword arguments to [`MatrixAlgebraKit.select_algorithm`](@ref): + +```julia +# Store configuration without picking a specific algorithm: +alg = DefaultAlgorithm(; positive = true) + +# Equivalent to qr_compact(A; positive = true): +Q, R = qr_compact(A; alg) +``` + +```@docs; canonical=false +DefaultAlgorithm +``` + +## Available Algorithm Types + +The following high-level algorithm types are available. +They all accept an optional `driver` keyword to select the computational backend; see [Driver Selection](@ref sec_driverselection) for details. + +| Algorithm | Applicable decompositions | Key keyword arguments | +|:----------|:--------------------------|:----------------------| +| [`Householder`](@ref) | QR, LQ | `positive`, `pivoted`, `blocksize` | +| [`DivideAndConquer`](@ref) | SVD, eigh | `fixgauge` | +| [`SafeDivideAndConquer`](@ref) | SVD, eigh | `fixgauge` | +| [`QRIteration`](@ref) | SVD, eigh, eig, Schur | `fixgauge`, `expert`, `permute`, `scale` | +| [`Bisection`](@ref) | eigh, SVD | `fixgauge` | +| [`Jacobi`](@ref) | eigh, SVD | `fixgauge` | +| [`RobustRepresentations`](@ref) | eigh | `fixgauge` | +| [`SVDViaPolar`](@ref) | SVD | `fixgauge`, `tol` | +| [`PolarViaSVD`](@ref) | polar | positional `svd_alg` argument | +| [`PolarNewton`](@ref) | polar | `maxiter`, `tol` | + +For full docstring details on each algorithm type, see the corresponding section in [Decompositions](@ref). + +## [Driver Selection](@id sec_driverselection) + +!!! note "Expert use case" + Selecting a specific driver is an advanced feature intended for users who need to target a specific computational backend, such as a GPU. + For most use cases, the default driver selection is sufficient. + +Each algorithm in MatrixAlgebraKit can optionally accept a `driver` keyword argument to explicitly select the computational backend. +By default, the driver is set to `DefaultDriver()`, which automatically selects the most appropriate backend based on the input matrix type. +The available drivers are: + +```@autodocs; canonical=false +Modules = [MatrixAlgebraKit] +Filter = t -> t isa Type && t <: MatrixAlgebraKit.Driver +``` + +For example, to force LAPACK for a generic matrix type, or to use a GPU backend: + +```julia +using MatrixAlgebraKit +using MatrixAlgebraKit: LAPACK, CUSOLVER # driver types are not exported by default + +# Default: driver is selected automatically based on the input type +U, S, Vᴴ = svd_compact(A) +U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer()) + +# Expert: explicitly select LAPACK +U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer(; driver = LAPACK())) + +# Expert: use a GPU backend (requires loading the appropriate extension) +U, S, Vᴴ = svd_compact(A; alg = QRIteration(; driver = CUSOLVER())) +``` + +Similarly, for QR decompositions: + +```julia +using MatrixAlgebraKit: LAPACK # driver types are not exported by default + +# Default: driver is selected automatically +Q, R = qr_compact(A) +Q, R = qr_compact(A; alg = Householder()) + +# Expert: explicitly select a driver +Q, R = qr_compact(A; alg = Householder(; driver = LAPACK())) +``` diff --git a/docs/src/user_interface/decompositions.md b/docs/src/user_interface/decompositions.md index c2df35b13..1e74e71d8 100644 --- a/docs/src/user_interface/decompositions.md +++ b/docs/src/user_interface/decompositions.md @@ -16,7 +16,7 @@ f!(A, [F]; kwargs...) -> F... Here, the input matrix is always the first argument, and optionally the output can be provided as well. The keywords are algorithm-specific, and can be used to influence the behavior of the algorithms. -To check what algorithm is used by default for a given factorization `f` and input `A`, and by extension which keyword arguments it takes, you can call [`MatrixAlgebraKit.default_algorithm(f, A)`](@ref) and check the documentation of resulting algorithm type. +For a full description of how to select and configure algorithms, see [Algorithm Selection](@ref sec_algorithmselection). Importantly, for generic code patterns it is recommended to always use the output `F` explicitly, since some implementations may not be able to reuse the provided memory. Additionally, the `f!` method typically assumes that it is allowed to destroy the input `A`, and making use of the contents of `A` afterwards should be deemed as undefined behavior. @@ -40,10 +40,11 @@ lq_full lq_compact ``` -The following algorithm is available for QR and LQ decompositions: +The following algorithms are available for QR and LQ decompositions: -```@docs; canonical=false -Householder +```@autodocs; canonical=false +Modules = [MatrixAlgebraKit] +Filter = t -> t isa Type && (t <: MatrixAlgebraKit.QRAlgorithms || t <: MatrixAlgebraKit.LQAlgorithms) ``` ## Eigenvalue Decomposition @@ -387,54 +388,6 @@ norm(A * N1') < 1e-14 && norm(A * N2') < 1e-14 && true ``` -## [Driver Selection](@id sec_driverselection) - -!!! note "Expert use case" - Selecting a specific driver is an advanced feature intended for users who need to target a specific computational backend, such as a GPU. For most use cases, the default driver selection is sufficient. - -Each algorithm in MatrixAlgebraKit can optionally accept a `driver` keyword argument to explicitly select the computational backend. -By default, the driver is set to `DefaultDriver()`, which automatically selects the most appropriate backend based on the input matrix type. -The available drivers are: - -```@docs; canonical=false -MatrixAlgebraKit.DefaultDriver -MatrixAlgebraKit.LAPACK -MatrixAlgebraKit.CUSOLVER -MatrixAlgebraKit.ROCSOLVER -MatrixAlgebraKit.GLA -MatrixAlgebraKit.Native -``` - -For example, to force LAPACK for a generic matrix type, or to use a GPU backend: - -```julia -using MatrixAlgebraKit -using MatrixAlgebraKit: LAPACK, CUSOLVER # driver types are not exported by default - -# Default: driver is selected automatically based on the input type -U, S, Vᴴ = svd_compact(A) -U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer()) - -# Expert: explicitly select LAPACK -U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer(; driver = LAPACK())) - -# Expert: use a GPU backend (requires loading the appropriate extension) -U, S, Vᴴ = svd_compact(A; alg = QRIteration(; driver = CUSOLVER())) -``` - -Similarly, for QR decompositions: - -```julia -using MatrixAlgebraKit: LAPACK # driver types are not exported by default - -# Default: driver is selected automatically -Q, R = qr_compact(A) -Q, R = qr_compact(A; alg = Householder()) - -# Expert: explicitly select a driver -Q, R = qr_compact(A; alg = Householder(; driver = LAPACK())) -``` - ## [Gauge choices](@id sec_gaugefix) Both eigenvalue and singular value decompositions have residual gauge degrees of freedom even when the eigenvalues or singular values are unique. From b6612d719235cd076bdafba9259df35d1ec11d1d Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Mon, 23 Mar 2026 15:54:28 -0400 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Lander Burgelman <39218680+leburgel@users.noreply.github.com> --- docs/src/user_interface/algorithms.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/src/user_interface/algorithms.md b/docs/src/user_interface/algorithms.md index c05bc11b4..b05d7cfdf 100644 --- a/docs/src/user_interface/algorithms.md +++ b/docs/src/user_interface/algorithms.md @@ -11,7 +11,8 @@ This page explains how to override that default, what algorithm types are availa ## The `alg` Keyword -The `alg` keyword is interpreted by [`MatrixAlgebraKit.select_algorithm`](@ref), which accepts five forms, e.g.: +The `alg` keyword is interpreted by [`MatrixAlgebraKit.select_algorithm`](@ref), which accepts five different forms for specifying an algorithm and its configuration. +For example, for `qr_compact` these forms look like: ```julia # Form 1: No alg — algorithm selected automatically based on function and array type. @@ -62,7 +63,7 @@ U, S, Vᴴ = svd_compact(A; alg = SafeDivideAndConquer(; fixgauge = false)) ## The `DefaultAlgorithm` Sentinel -Package developers who want to store algorithm configuration without committing to a specific algorithm can use `DefaultAlgorithm`. +Package developers who want to store an algorithm configuration without committing to a specific algorithm can use `DefaultAlgorithm`. It defers algorithm selection to call time, forwarding its stored keyword arguments to [`MatrixAlgebraKit.select_algorithm`](@ref): ```julia From 6beae739ecd2cb2dfa44a603b788490a4fb19734 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 23 Mar 2026 15:54:47 -0400 Subject: [PATCH 3/3] array type -> input type --- docs/src/user_interface/algorithms.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/user_interface/algorithms.md b/docs/src/user_interface/algorithms.md index b05d7cfdf..74c85a9b9 100644 --- a/docs/src/user_interface/algorithms.md +++ b/docs/src/user_interface/algorithms.md @@ -6,7 +6,7 @@ CollapsedDocStrings = true # [Algorithm Selection](@id sec_algorithmselection) All factorization functions in MatrixAlgebraKit accept an optional `alg` keyword argument that controls which algorithm is used and how it is configured. -By default, an appropriate algorithm is selected automatically based on the function and the array type. +By default, an appropriate algorithm is selected automatically based on the function and the input types. This page explains how to override that default, what algorithm types are available, and how to configure them. ## The `alg` Keyword @@ -15,7 +15,7 @@ The `alg` keyword is interpreted by [`MatrixAlgebraKit.select_algorithm`](@ref), For example, for `qr_compact` these forms look like: ```julia -# Form 1: No alg — algorithm selected automatically based on function and array type. +# Form 1: No alg — algorithm selected automatically based on function and input type. Q, R = qr_compact(A); # Form 2: Symbol — creates Algorithm{:Householder}(; positive=false). @@ -41,7 +41,7 @@ MatrixAlgebraKit.select_algorithm ## Discovering the Default Algorithm -To check which algorithm is used by default for a given function and array type, call [`MatrixAlgebraKit.default_algorithm`](@ref). +To check which algorithm is used by default for a given function and input type, call [`MatrixAlgebraKit.default_algorithm`](@ref). The available keyword arguments depend on the algorithm type; refer to the docstrings listed in [Available Algorithm Types](@ref) below. ```@docs; canonical=false