Skip to content

Commit 5cc0adc

Browse files
authored
Merge branch 'master' into rank-qrpivoted-documentation
2 parents 60500d6 + b265fea commit 5cc0adc

33 files changed

+1564
-111
lines changed

src/adjtrans.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,3 +552,20 @@ conj(A::Adjoint) = transpose(A.parent)
552552
function Base.replace_in_print_matrix(A::AdjOrTrans,i::Integer,j::Integer,s::AbstractString)
553553
Base.replace_in_print_matrix(parent(A), j, i, s)
554554
end
555+
556+
# Special adjoint/transpose methods for Adjoint/Transpose that have been reshaped as a vector
557+
# these are used in transposing banded matrices by forwarding the operation to the bands
558+
"""
559+
_vectranspose(A::AbstractVector)::AbstractVector
560+
561+
Compute `vec(transpose(A))`, but avoid an allocating reshape if possible
562+
"""
563+
_vectranspose(A::AbstractVector) = vec(transpose(A))
564+
_vectranspose(A::Base.ReshapedArray{<:Any,1,<:TransposeAbsVec}) = transpose(parent(A))
565+
"""
566+
_vecadjoint(A::AbstractVector)::AbstractVector
567+
568+
Compute `vec(adjoint(A))`, but avoid an allocating reshape if possible
569+
"""
570+
_vecadjoint(A::AbstractVector) = vec(adjoint(A))
571+
_vecadjoint(A::Base.ReshapedArray{<:Any,1,<:AdjointAbsVec}) = adjoint(parent(A))

src/bidiag.jl

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -308,23 +308,13 @@ for func in (:conj, :copy, :real, :imag)
308308
end
309309
isreal(M::Bidiagonal) = isreal(M.dv) && isreal(M.ev)
310310

311-
adjoint(B::Bidiagonal{<:Number}) = Bidiagonal(vec(adjoint(B.dv)), vec(adjoint(B.ev)), B.uplo == 'U' ? :L : :U)
312-
adjoint(B::Bidiagonal{<:Number, <:Base.ReshapedArray{<:Number,1,<:Adjoint}}) =
313-
Bidiagonal(adjoint(parent(B.dv)), adjoint(parent(B.ev)), B.uplo == 'U' ? :L : :U)
314-
transpose(B::Bidiagonal{<:Number}) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? :L : :U)
311+
adjoint(B::Bidiagonal) = Bidiagonal(_vecadjoint(B.dv), _vecadjoint(B.ev), B.uplo == 'U' ? :L : :U)
312+
transpose(B::Bidiagonal) = Bidiagonal(_vectranspose(B.dv), _vectranspose(B.ev), B.uplo == 'U' ? :L : :U)
315313
permutedims(B::Bidiagonal) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? 'L' : 'U')
316314
function permutedims(B::Bidiagonal, perm)
317315
Base.checkdims_perm(axes(B), axes(B), perm)
318316
NTuple{2}(perm) == (2, 1) ? permutedims(B) : B
319317
end
320-
function Base.copy(aB::Adjoint{<:Any,<:Bidiagonal})
321-
B = aB.parent
322-
return Bidiagonal(map(x -> copy.(adjoint.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)
323-
end
324-
function Base.copy(tB::Transpose{<:Any,<:Bidiagonal})
325-
B = tB.parent
326-
return Bidiagonal(map(x -> copy.(transpose.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)
327-
end
328318

329319
@noinline function throw_zeroband_error(A)
330320
uplo = A.uplo
@@ -1271,26 +1261,22 @@ function _dibimul_nonzeroalpha!(C::Bidiagonal, A::Diagonal, B::Bidiagonal, _add)
12711261
end
12721262

12731263
function mul(A::UpperOrUnitUpperTriangular, B::Bidiagonal)
1274-
TS = promote_op(matprod, eltype(A), eltype(B))
1275-
C = mul!(similar(A, TS, size(A)), A, B)
1264+
C = _mul(A, B)
12761265
return B.uplo == 'U' ? UpperTriangular(C) : C
12771266
end
12781267

12791268
function mul(A::LowerOrUnitLowerTriangular, B::Bidiagonal)
1280-
TS = promote_op(matprod, eltype(A), eltype(B))
1281-
C = mul!(similar(A, TS, size(A)), A, B)
1269+
C = _mul(A, B)
12821270
return B.uplo == 'L' ? LowerTriangular(C) : C
12831271
end
12841272

12851273
function mul(A::Bidiagonal, B::UpperOrUnitUpperTriangular)
1286-
TS = promote_op(matprod, eltype(A), eltype(B))
1287-
C = mul!(similar(B, TS, size(B)), A, B)
1274+
C = _mul(A, B)
12881275
return A.uplo == 'U' ? UpperTriangular(C) : C
12891276
end
12901277

12911278
function mul(A::Bidiagonal, B::LowerOrUnitLowerTriangular)
1292-
TS = promote_op(matprod, eltype(A), eltype(B))
1293-
C = mul!(similar(B, TS, size(B)), A, B)
1279+
C = _mul(A, B)
12941280
return A.uplo == 'L' ? LowerTriangular(C) : C
12951281
end
12961282

@@ -1362,14 +1348,10 @@ function ldiv!(c::AbstractVecOrMat, A::Bidiagonal, b::AbstractVecOrMat)
13621348
end
13631349
return c
13641350
end
1365-
ldiv!(A::AdjOrTrans{<:Any,<:Bidiagonal}, b::AbstractVecOrMat) = @inline ldiv!(b, A, b)
1366-
ldiv!(c::AbstractVecOrMat, A::AdjOrTrans{<:Any,<:Bidiagonal}, b::AbstractVecOrMat) =
1367-
(t = wrapperop(A); _rdiv!(t(c), t(b), t(A)); return c)
13681351

13691352
### Generic promotion methods and fallbacks
13701353
\(A::Bidiagonal, B::AbstractVecOrMat) =
13711354
ldiv!(matprod_dest(A, B, promote_op(\, eltype(A), eltype(B))), A, B)
1372-
\(xA::AdjOrTrans{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = copy(xA) \ B
13731355

13741356
### Triangular specializations
13751357
for tri in (:UpperTriangular, :UnitUpperTriangular)
@@ -1441,9 +1423,6 @@ function _rdiv!(C::AbstractMatrix, A::AbstractMatrix, B::Bidiagonal)
14411423
C
14421424
end
14431425
rdiv!(A::AbstractMatrix, B::Bidiagonal) = @inline _rdiv!(A, A, B)
1444-
rdiv!(A::AbstractMatrix, B::AdjOrTrans{<:Any,<:Bidiagonal}) = @inline _rdiv!(A, A, B)
1445-
_rdiv!(C::AbstractMatrix, A::AbstractMatrix, B::AdjOrTrans{<:Any,<:Bidiagonal}) =
1446-
(t = wrapperop(B); ldiv!(t(C), t(B), t(A)); return C)
14471426

14481427
/(A::AbstractMatrix, B::Bidiagonal) =
14491428
_rdiv!(similar(A, promote_op(/, eltype(A), eltype(B)), size(A)), A, B)
@@ -1476,15 +1455,9 @@ function /(D::Diagonal, B::Bidiagonal)
14761455
return B.uplo == 'U' ? UpperTriangular(A) : LowerTriangular(A)
14771456
end
14781457

1479-
/(A::AbstractMatrix, B::Transpose{<:Any,<:Bidiagonal}) = A / copy(B)
1480-
/(A::AbstractMatrix, B::Adjoint{<:Any,<:Bidiagonal}) = A / copy(B)
14811458
# disambiguation
14821459
/(A::AdjointAbsVec, B::Bidiagonal) = adjoint(adjoint(B) \ parent(A))
14831460
/(A::TransposeAbsVec, B::Bidiagonal) = transpose(transpose(B) \ parent(A))
1484-
/(A::AdjointAbsVec, B::Transpose{<:Any,<:Bidiagonal}) = adjoint(adjoint(B) \ parent(A))
1485-
/(A::TransposeAbsVec, B::Transpose{<:Any,<:Bidiagonal}) = transpose(transpose(B) \ parent(A))
1486-
/(A::AdjointAbsVec, B::Adjoint{<:Any,<:Bidiagonal}) = adjoint(adjoint(B) \ parent(A))
1487-
/(A::TransposeAbsVec, B::Adjoint{<:Any,<:Bidiagonal}) = transpose(transpose(B) \ parent(A))
14881461

14891462
factorize(A::Bidiagonal) = A
14901463
function inv(B::Bidiagonal{T}) where T

src/diagonal.jl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -906,11 +906,8 @@ end
906906
end
907907

908908
conj(D::Diagonal) = Diagonal(conj(D.diag))
909-
transpose(D::Diagonal{<:Number}) = D
910-
transpose(D::Diagonal) = Diagonal(transpose.(D.diag))
911-
adjoint(D::Diagonal{<:Number}) = Diagonal(vec(adjoint(D.diag)))
912-
adjoint(D::Diagonal{<:Number,<:Base.ReshapedArray{<:Number,1,<:Adjoint}}) = Diagonal(adjoint(parent(D.diag)))
913-
adjoint(D::Diagonal) = Diagonal(adjoint.(D.diag))
909+
transpose(D::Diagonal) = Diagonal(_vectranspose(D.diag))
910+
adjoint(D::Diagonal) = Diagonal(_vecadjoint(D.diag))
914911
permutedims(D::Diagonal) = D
915912
permutedims(D::Diagonal, perm) = (Base.checkdims_perm(axes(D), axes(D), perm); D)
916913

src/lu.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ end
652652

653653
# Initialize variables
654654
info = 0
655-
fill!(du2, 0)
655+
fill!(du2, zero(eltype(du2)))
656656

657657
@inbounds begin
658658
for i = 1:n

src/matmul.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ end
5151

5252
# Matrix-vector multiplication
5353
function (*)(A::StridedMaybeAdjOrTransMat{T}, x::StridedVector{S}) where {T<:BlasFloat,S<:Real}
54+
matmul_size_check(size(A), size(x))
5455
TS = promote_op(matprod, T, S)
5556
y = isconcretetype(TS) ? convert(AbstractVector{TS}, x) : x
5657
mul!(similar(x, TS, size(A,1)), A, y)
5758
end
5859
function (*)(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S}
60+
matmul_size_check(size(A), size(x))
5961
TS = promote_op(matprod, T, S)
6062
mul!(similar(x, TS, axes(A,1)), A, x)
6163
end
@@ -113,7 +115,10 @@ julia> [1 1; 0 1] * [1 0; 1 1]
113115
"""
114116
(*)(A::AbstractMatrix, B::AbstractMatrix) = mul(A, B)
115117
# we add an extra level of indirection to avoid ambiguities in *
116-
function mul(A::AbstractMatrix, B::AbstractMatrix)
118+
# We also define the core functionality within _mul to reuse the code elsewhere
119+
mul(A::AbstractMatrix, B::AbstractMatrix) = _mul(A, B)
120+
function _mul(A::AbstractMatrix, B::AbstractMatrix)
121+
matmul_size_check(size(A), size(B))
117122
TS = promote_op(matprod, eltype(A), eltype(B))
118123
mul!(matprod_dest(A, B, TS), A, B)
119124
end

src/structuredbroadcast.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function copyto!(dest::Diagonal, bc::Broadcasted{<:StructuredMatrixStyle})
212212
isvalidstructbc(dest, bc) || return copyto!(dest, convert(Broadcasted{Nothing}, bc))
213213
axs = axes(dest)
214214
axes(bc) == axs || Broadcast.throwdm(axes(bc), axs)
215-
for i in axs[1]
215+
for i in eachindex(dest.diag)
216216
dest.diag[i] = @inbounds bc[BandIndex(0, i)]
217217
end
218218
return dest
@@ -222,15 +222,15 @@ function copyto!(dest::Bidiagonal, bc::Broadcasted{<:StructuredMatrixStyle})
222222
isvalidstructbc(dest, bc) || return copyto!(dest, convert(Broadcasted{Nothing}, bc))
223223
axs = axes(dest)
224224
axes(bc) == axs || Broadcast.throwdm(axes(bc), axs)
225-
for i in axs[1]
225+
for i in eachindex(dest.dv)
226226
dest.dv[i] = @inbounds bc[BandIndex(0, i)]
227227
end
228228
if dest.uplo == 'U'
229-
for i = 1:size(dest, 1)-1
229+
for i in eachindex(dest.ev)
230230
dest.ev[i] = @inbounds bc[BandIndex(1, i)]
231231
end
232232
else
233-
for i = 1:size(dest, 1)-1
233+
for i in eachindex(dest.ev)
234234
dest.ev[i] = @inbounds bc[BandIndex(-1, i)]
235235
end
236236
end
@@ -257,13 +257,13 @@ function copyto!(dest::Tridiagonal, bc::Broadcasted{<:StructuredMatrixStyle})
257257
isvalidstructbc(dest, bc) || return copyto!(dest, convert(Broadcasted{Nothing}, bc))
258258
axs = axes(dest)
259259
axes(bc) == axs || Broadcast.throwdm(axes(bc), axs)
260-
for i in axs[1]
260+
for i in eachindex(dest.d)
261261
dest.d[i] = @inbounds bc[BandIndex(0, i)]
262262
end
263-
for i = 1:size(dest, 1)-1
263+
for i in eachindex(dest.du)
264264
dest.du[i] = @inbounds bc[BandIndex(1, i)]
265265
end
266-
for i = 1:size(dest, 1)-1
266+
for i in eachindex(dest.dl)
267267
dest.dl[i] = @inbounds bc[BandIndex(-1, i)]
268268
end
269269
return dest

src/symmetric.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,12 +710,14 @@ end
710710
mul(A::HermOrSym, B::HermOrSym) = A * copyto!(similar(parent(B)), B)
711711
# catch a few potential BLAS-cases
712712
function mul(A::HermOrSym{<:BlasFloat,<:StridedMatrix}, B::AdjOrTrans{<:BlasFloat,<:StridedMatrix})
713+
matmul_size_check(size(A), size(B))
713714
T = promote_type(eltype(A), eltype(B))
714715
mul!(similar(B, T, (size(A, 1), size(B, 2))),
715716
convert(AbstractMatrix{T}, A),
716717
copy_oftype(B, T)) # make sure the AdjOrTrans wrapper is resolved
717718
end
718719
function mul(A::AdjOrTrans{<:BlasFloat,<:StridedMatrix}, B::HermOrSym{<:BlasFloat,<:StridedMatrix})
720+
matmul_size_check(size(A), size(B))
719721
T = promote_type(eltype(A), eltype(B))
720722
mul!(similar(B, T, (size(A, 1), size(B, 2))),
721723
copy_oftype(A, T), # make sure the AdjOrTrans wrapper is resolved

src/symmetriceigen.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ eigencopy_oftype(A::Symmetric{<:Complex}, S) = copyto!(similar(parent(A), S), A)
1010
default_eigen_alg(A)
1111
1212
Return the default algorithm used to solve the eigensystem `A v = λ v` for a symmetric matrix `A`.
13-
Defaults to `LinearAlegbra.DivideAndConquer()`, which corresponds to the LAPACK function `LAPACK.syevd!`.
13+
Defaults to `LinearAlegbra.RobustRepresentations()`, which corresponds to the LAPACK function `LAPACK.syevr!`.
1414
"""
15-
default_eigen_alg(@nospecialize(A)) = DivideAndConquer()
15+
default_eigen_alg(@nospecialize(A)) = RobustRepresentations()
1616

1717
# Eigensolvers for symmetric and Hermitian matrices
1818
function eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; alg::Algorithm = default_eigen_alg(A), sortby::Union{Function,Nothing}=nothing)
@@ -37,9 +37,9 @@ matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vec
3737
Iterating the decomposition produces the components `F.values` and `F.vectors`.
3838
3939
`alg` specifies which algorithm and LAPACK method to use for eigenvalue decomposition:
40-
- `alg = DivideAndConquer()` (default): Calls `LAPACK.syevd!`.
40+
- `alg = DivideAndConquer()`: Calls `LAPACK.syevd!`.
4141
- `alg = QRIteration()`: Calls `LAPACK.syev!`.
42-
- `alg = RobustRepresentations()`: Multiple relatively robust representations method, Calls `LAPACK.syevr!`.
42+
- `alg = RobustRepresentations()` (default): Multiple relatively robust representations method, Calls `LAPACK.syevr!`.
4343
4444
See James W. Demmel et al, SIAM J. Sci. Comput. 30, 3, 1508 (2008) for
4545
a comparison of the accuracy and performance of different algorithms.
@@ -140,14 +140,18 @@ end
140140
Return the eigenvalues of `A`.
141141
142142
`alg` specifies which algorithm and LAPACK method to use for eigenvalue decomposition:
143-
- `alg = DivideAndConquer()` (default): Calls `LAPACK.syevd!`.
143+
- `alg = DivideAndConquer()`: Calls `LAPACK.syevd!`.
144144
- `alg = QRIteration()`: Calls `LAPACK.syev!`.
145-
- `alg = RobustRepresentations()`: Multiple relatively robust representations method, Calls `LAPACK.syevr!`.
145+
- `alg = RobustRepresentations()` (default): Multiple relatively robust representations method, Calls `LAPACK.syevr!`.
146146
147147
See James W. Demmel et al, SIAM J. Sci. Comput. 30, 3, 1508 (2008) for
148148
a comparison of the accuracy and performance of different methods.
149149
150150
The default `alg` used may change in the future.
151+
152+
!!! compat "Julia 1.12"
153+
The `alg` keyword argument requires Julia 1.12 or later.
154+
151155
"""
152156
function eigvals(A::RealHermSymComplexHerm; alg::Algorithm = default_eigen_alg(A), sortby::Union{Function,Nothing}=nothing)
153157
S = eigtype(eltype(A))

src/uniformscaling.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,17 @@ function (-)(J::UniformScaling{<:Complex}, A::Hermitian)
217217
return B
218218
end
219219

220+
function (+)(A::AdjOrTransAbsMat, J::UniformScaling)
221+
checksquare(A)
222+
op = wrapperop(A)
223+
op(op(A) + op(J))
224+
end
225+
function (-)(J::UniformScaling, A::AdjOrTransAbsMat)
226+
checksquare(A)
227+
op = wrapperop(A)
228+
op(op(J) - op(A))
229+
end
230+
220231
function (+)(A::AbstractMatrix, J::UniformScaling)
221232
checksquare(A)
222233
B = copymutable_oftype(A, Base.promote_op(+, eltype(A), typeof(J)))
@@ -338,7 +349,8 @@ function ==(A::AbstractMatrix, J::UniformScaling)
338349
size(A, 1) == size(A, 2) || return false
339350
iszero(J.λ) && return iszero(A)
340351
isone(J.λ) && return isone(A)
341-
return A == J.λ*one(A)
352+
isdiag(A) || return false
353+
return all(==(J.λ), diagview(A))
342354
end
343355
function ==(A::StridedMatrix, J::UniformScaling)
344356
size(A, 1) == size(A, 2) || return false

test/adjtrans.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ isdefined(Main, :pruned_old_LA) || @eval Main include("prune_old_LA.jl")
66

77
using Test, LinearAlgebra
88

9-
const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test")
9+
const BASE_TEST_PATH = joinpath(dirname(pathof(LinearAlgebra)), "..", "test")
10+
const TESTHELPERS = joinpath(BASE_TEST_PATH, "testhelpers")
1011

11-
isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl"))
12+
isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($TESTHELPERS, "OffsetArrays.jl"))
1213
using .Main.OffsetArrays
1314

14-
isdefined(Main, :ImmutableArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "ImmutableArrays.jl"))
15+
isdefined(Main, :ImmutableArrays) || @eval Main include(joinpath($TESTHELPERS, "ImmutableArrays.jl"))
1516
using .Main.ImmutableArrays
1617

1718
@testset "Adjoint and Transpose inner constructor basics" begin

0 commit comments

Comments
 (0)