Skip to content

Commit 652fd7c

Browse files
Merge pull request #391 from ChrisRackauckas-Claude/fix-lu-componentmatrix
Make lu/qr of ComponentMatrix preserve the wrapper on factors
2 parents 23ed12d + f37b6e7 commit 652fd7c

4 files changed

Lines changed: 58 additions & 3 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ComponentArrays"
22
uuid = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66"
33
authors = ["Jonnie Diegelman <47193959+jonniedie@users.noreply.github.com>"]
4-
version = "0.15.41"
4+
version = "0.15.42"
55

66
[deps]
77
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

src/ComponentArrays.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import StaticArrayInterface, ArrayInterface, Functors
55
import ConstructionBase
66
import Adapt
77

8-
using LinearAlgebra: LinearAlgebra, Adjoint, Cholesky, Diagonal, I, LU, Transpose,
9-
UniformScaling, axpby!, axpy!, ldiv!
8+
using LinearAlgebra: LinearAlgebra, Adjoint, Cholesky, ColumnNorm, Diagonal, I, LU,
9+
NoPivot, RowMaximum, RowNonZero, Transpose, UniformScaling, axpby!, axpy!, ldiv!
1010
using StaticArraysCore: StaticArray, SArray, SVector
1111

1212
const FlatIdx = Union{Integer, CartesianIndex, CartesianIndices, AbstractArray{<:Integer}}

src/linear_algebra.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,40 @@ function ArrayInterface.lu_instance(x::ComponentMatrix)
88
return LU{luT}(similar(x), ipiv, info)
99
end
1010

11+
# The generic `lu`/`qr` copy through `similar(A, T, dims)`, which drops the axes
12+
# and returns a plain `Matrix`, whereas the in-place `lu!`/`qr!` (ComponentMatrix
13+
# is strided, so they hit LAPACK directly) keep the ComponentMatrix wrapper on the
14+
# factors. Make the out-of-place versions and the `ArrayInterface` instance
15+
# functions preserve the wrapper too, so callers that type a cache from the
16+
# instance functions and later store either variant (e.g. LinearSolve) don't hit
17+
# a cache type mismatch.
18+
function LinearAlgebra.lu(
19+
A::ComponentMatrix, pivot::Union{NoPivot, RowNonZero, RowMaximum} = RowMaximum();
20+
kwargs...,
21+
)
22+
F = LinearAlgebra.lu(getdata(A), pivot; kwargs...)
23+
return LU(ComponentArray(F.factors, getaxes(A)), F.ipiv, F.info)
24+
end
25+
26+
function LinearAlgebra.qr(
27+
A::ComponentMatrix, pivot::Union{NoPivot, ColumnNorm} = NoPivot();
28+
kwargs...,
29+
)
30+
F = LinearAlgebra.qr(getdata(A), pivot; kwargs...)
31+
return _rewrap_qr(F, getaxes(A))
32+
end
33+
34+
function ArrayInterface.qr_instance(A::ComponentMatrix, pivot = NoPivot())
35+
F = ArrayInterface.qr_instance(getdata(A), pivot)
36+
return _rewrap_qr(F, getaxes(A))
37+
end
38+
39+
function _rewrap_qr(F::LinearAlgebra.QRCompactWY, ax)
40+
return LinearAlgebra.QRCompactWY(ComponentArray(F.factors, ax), F.T)
41+
end
42+
_rewrap_qr(F::LinearAlgebra.QRPivoted, ax) = LinearAlgebra.QRPivoted(ComponentArray(F.factors, ax), F.τ, F.jpvt)
43+
_rewrap_qr(F, ax) = F
44+
1145
# Helpers for dealing with adjoints and such
1246
_first_axis(x::AbstractComponentVecOrMat) = getaxes(x)[1]
1347

test/math_tests.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,25 @@ s2_D = out2 * in2'
143143
(FlatAxis(), Axis(u2 = 1))
144144

145145
@test ComponentArrays.ArrayInterface.lu_instance(cmat).factors isa ComponentMatrix
146+
147+
# `lu`, `lu!`, and `lu_instance` (same for qr) must all keep the ComponentMatrix
148+
# wrapper on the factors, or caches typed from the instance functions break when
149+
# a `lu`/`qr` result is stored in them (LinearSolve's default solver does this;
150+
# see the PR #390 downstream CI failure).
151+
let A = cmat + I
152+
F = lu(A)
153+
@test F.factors isa ComponentMatrix
154+
@test typeof(F) === typeof(ComponentArrays.ArrayInterface.lu_instance(A))
155+
@test typeof(F) === typeof(lu!(copy(A)))
156+
@test getdata(F.factors) == lu(getdata(A)).factors
157+
@test F \ getdata(ca) getdata(A) \ getdata(ca)
158+
159+
Fqr = qr(A)
160+
@test Fqr.factors isa ComponentMatrix
161+
@test typeof(Fqr) === typeof(ComponentArrays.ArrayInterface.qr_instance(A, NoPivot()))
162+
@test typeof(Fqr) === typeof(qr!(copy(A)))
163+
@test Fqr \ getdata(ca) getdata(A) \ getdata(ca)
164+
@test typeof(qr(A, ColumnNorm())) === typeof(qr!(copy(A), ColumnNorm())) ===
165+
typeof(ComponentArrays.ArrayInterface.qr_instance(A, ColumnNorm()))
166+
end
146167
@test ComponentArrays.ArrayInterface.parent_type(cmat) === Matrix{Float64}

0 commit comments

Comments
 (0)