|
19 | 19 | # Orth functions |
20 | 20 | # -------------- |
21 | 21 | """ |
22 | | - left_orth(A; [kind::Symbol, atol::Real=0, rtol::Real=0, alg]) -> V, C |
23 | | - left_orth!(A, [VC]; [kind::Symbol, atol::Real=0, rtol::Real=0, alg]) -> V, C |
| 22 | + left_orth(A; [kind::Symbol, trunc, alg_qr, alg_polar, alg_svd]) -> V, C |
| 23 | + left_orth!(A, [VC]; [kind::Symbol, trunc, alg_qr, alg_polar, alg_svd]) -> V, C |
24 | 24 |
|
25 | 25 | Compute an orthonormal basis `V` for the image of the matrix `A` of size `(m, n)`, |
26 | 26 | as well as a matrix `C` (the corestriction) such that `A` factors as `A = V * C`. |
27 | 27 | The keyword argument `kind` can be used to specify the specific orthogonal decomposition |
28 | | -that should be used to factor `A`, whereas `atol` and `rtol` can be used to control the |
| 28 | +that should be used to factor `A`, whereas `trunc` can be used to control the |
29 | 29 | precision in determining the rank of `A` via its singular values. |
30 | 30 |
|
31 | 31 | This is a high-level wrapper and will use one of the decompositions |
32 | | -`qr!`, `svd!`, and `left_polar!` to compute the orthogonal basis `V`, as controlled |
| 32 | +`qr_compact!`, `svd_compact!`/`svd_trunc!`, and `left_polar!` to compute the orthogonal basis `V`, as controlled |
33 | 33 | by the keyword arguments. |
34 | 34 |
|
35 | 35 | When `kind` is provided, its possible values are |
36 | 36 |
|
37 | | -* `kind == :qrpos`: `V` and `C` are computed using the positive QR decomposition. |
38 | | - This requires `iszero(atol) && iszero(rtol)` and `left_orth!(A, [VC])` is equivalent to |
| 37 | +* `kind == :qr`: `V` and `C` are computed using the QR decomposition. |
| 38 | + This requires `isnothing(trunc)` and `left_orth!(A, [VC])` is equivalent to |
39 | 39 | `qr_compact!(A, [VC], alg)` with a default value `alg = select_algorithm(qr_compact!, A; positive=true)` |
40 | 40 |
|
41 | | -* `kind == :qr`: `V` and `C` are computed using the QR decomposition, |
42 | | - This requires `iszero(atol) && iszero(rtol)` and `left_orth!(A, [VC])` is equivalent to |
43 | | - `qr_compact!(A, [VC], alg)` with a default value `alg = select_algorithm(qr_compact!, A)` |
44 | | -
|
45 | 41 | * `kind == :polar`: `V` and `C` are computed using the polar decomposition, |
46 | | - This requires `iszero(atol) && iszero(rtol)` and `left_orth!(A, [VC])` is equivalent to |
| 42 | + This requires `isnothing(trunc)` and `left_orth!(A, [VC])` is equivalent to |
47 | 43 | `left_polar!(A, [VC], alg)` with a default value `alg = select_algorithm(left_polar!, A)` |
48 | 44 |
|
49 | | -* `kind == :svd`: `V` and `C` are computed using the singular value decomposition `svd_trunc!`, |
50 | | - where `V` will contain the left singular vectors corresponding to the singular values that |
51 | | - are larger than `max(atol, rtol * σ₁)`, where `σ₁` is the largest singular value of `A`. |
52 | | - `C` is computed as the product of the singular values and the right singular vectors, |
53 | | - i.e. with `U, S, Vᴴ = svd_trunc!(A)`, we have `V = U` and `C = S * Vᴴ`. |
| 45 | +* `kind == :svd`: `V` and `C` are computed using the singular value decomposition `svd_compact!` |
| 46 | + if no truncation is specified through the `trunc` keyword argument or `svd_trunc!` |
| 47 | + if truncation is specified through the `trunc` keyword argument. |
| 48 | + `V` will contain the left singular vectors and `C` is computed as the product of the singular |
| 49 | + values and the right singular vectors, i.e. with `U, S, Vᴴ = svd(A)`, we have |
| 50 | + `V = U` and `C = S * Vᴴ`. |
54 | 51 |
|
55 | | -When `kind` is not provided, the default value is `:qrpos` when `iszero(atol) && iszero(rtol)` |
| 52 | +When `kind` is not provided, the default value is `:qr` when `isnothing(trunc)` |
56 | 53 | and `:svd` otherwise. Finally, finer control is obtained by providing an explicit algorithm |
57 | | -using the `alg` keyword argument, which should be compatible with the chosen or default value |
58 | | -of `kind`. |
| 54 | +for backend factorizations through the `alg_qr`, `alg_polar`, and `alg_svd` keyword arguments, |
| 55 | +which will only be used if the corresponding factorization is called based on the other inputs. |
| 56 | +If NamedTuples are passed as `alg_qr`, `alg_polar`, or `alg_svd`, a default algorithm is chosen |
| 57 | +with `select_algorithm` and the NamedTuple is passed as keyword arguments to that algorithm. |
| 58 | +`alg_qr` defaults to `(; positive=true)` so that by default a positive QR decomposition will |
| 59 | +be used. |
59 | 60 |
|
60 | 61 | !!! note |
61 | 62 | The bang method `left_orth!` optionally accepts the output structure and possibly destroys |
|
80 | 81 | Compute an orthonormal basis `V = adjoint(Vᴴ)` for the coimage of the matrix `A`, i.e. |
81 | 82 | for the image of `adjoint(A)`, as well as a matrix `C` such that `A = C * Vᴴ`. |
82 | 83 | The keyword argument `kind` can be used to specify the specific orthogonal decomposition |
83 | | -that should be used to factor `A`, whereas `atol` and `rtol` can be used to control the |
| 84 | +that should be used to factor `A`, whereas `trunc` can be used to control the |
84 | 85 | precision in determining the rank of `A` via its singular values. |
85 | 86 |
|
86 | 87 | This is a high-level wrapper and will use call one of the decompositions |
87 | | -`qr!`, `svd!`, and `left_polar!` to compute the orthogonal basis `V`, as controlled |
88 | | -by the keyword arguments. |
| 88 | +`lq_compact!`, `svd_compact!`/`svd_trunc!`, and `right_polar!` to compute the |
| 89 | +orthogonal basis `V`, as controlled by the keyword arguments. |
89 | 90 |
|
90 | 91 | When `kind` is provided, its possible values are |
91 | 92 |
|
92 | | -* `kind == :lqpos`: `C` and `Vᴴ` are computed using the positive QR decomposition. |
93 | | - This requires `iszero(atol) && iszero(rtol)` and `right_orth!(A, [CVᴴ])` is equivalent to |
94 | | - `lq_compact!(A, [CVᴴ], alg)` with a default value `alg = select_algorithm(lq_compact!, A; positive=true)` |
95 | | -
|
96 | 93 | * `kind == :lq`: `C` and `Vᴴ` are computed using the QR decomposition, |
97 | | - This requires `iszero(atol) && iszero(rtol)` and `right_orth!(A, [CVᴴ])` is equivalent to |
98 | | - `lq_compact!(A, [CVᴴ], alg)` with a default value `alg = select_algorithm(lq_compact!, A))` |
| 94 | + This requires `isnothing(trunc)` and `right_orth!(A, [CVᴴ])` is equivalent to |
| 95 | + `lq_compact!(A, [CVᴴ], alg)` with a default value `alg = select_algorithm(lq_compact!, A; positive=true)` |
99 | 96 |
|
100 | 97 | * `kind == :polar`: `C` and `Vᴴ` are computed using the polar decomposition, |
101 | | - This requires `iszero(atol) && iszero(rtol)` and `right_orth!(A, [CVᴴ])` is equivalent to |
102 | | - `right_polar!(A, [CVᴴ], alg)` with a default value `alg = select_algorithm(right_polar!, A))` |
| 98 | + This requires `isnothing(trunc)` and `right_orth!(A, [CVᴴ])` is equivalent to |
| 99 | + `right_polar!(A, [CVᴴ], alg)` with a default value `alg = select_algorithm(right_polar!, A)` |
103 | 100 |
|
104 | | -* `kind == :svd`: `C` and `Vᴴ` are computed using the singular value decomposition `svd_trunc!`, |
105 | | - where `V = adjoint(Vᴴ)` will contain the right singular vectors corresponding to the singular |
106 | | - values that are larger than `max(atol, rtol * σ₁)`, where `σ₁` is the largest singular value of `A`. |
107 | | - `C` is computed as the product of the singular values and the right singular vectors, |
108 | | - i.e. with `U, S, Vᴴ = svd_trunc!(A)`, we have `C = rmul!(U, S)` and `Vᴴ = Vᴴ`. |
| 101 | +* `kind == :svd`: `C` and `Vᴴ` are computed using the singular value decomposition `svd_compact!` |
| 102 | + if no truncation is specified through the `trunc` keyword argument or `svd_trunc!` |
| 103 | + if truncation is specified through the `trunc` keyword argument. |
| 104 | + `V = adjoint(Vᴴ)` will contain the right singular vectors corresponding to the singular |
| 105 | + values and `C` is computed as the product of the singular values and the right singular vectors, |
| 106 | + i.e. with `U, S, Vᴴ = svd(A)`, we have `C = rmul!(U, S)` and `Vᴴ = Vᴴ`. |
109 | 107 |
|
110 | | -When `kind` is not provided, the default value is `:lqpos` when `iszero(atol) && iszero(rtol)` |
| 108 | +When `kind` is not provided, the default value is `:lq` when `isnothing(trunc)` |
111 | 109 | and `:svd` otherwise. Finally, finer control is obtained by providing an explicit algorithm |
112 | | -using the `alg` keyword argument, which should be compatible with the chosen or default value |
113 | | -of `kind`. |
| 110 | +for backend factorizations through the `alg_lq`, `alg_polar`, and `alg_svd` keyword arguments, |
| 111 | +which will only be used if the corresponding factorization is called based on the other inputs. |
| 112 | +If NamedTuples are passed as `alg_lq`, `alg_polar`, or `alg_svd`, a default algorithm is chosen |
| 113 | +with `select_algorithm` and the NamedTuple is passed as keyword arguments to that algorithm. |
| 114 | +`alg_lq` defaults to `(; positive=true)` so that by default a positive QR decomposition will |
| 115 | +be used. |
114 | 116 |
|
115 | 117 | !!! note |
116 | 118 | The bang method `right_orth!` optionally accepts the output structure and possibly destroys |
|
0 commit comments