Skip to content

Commit 475dad8

Browse files
2 parents a2358df + 47d02b7 commit 475dad8

File tree

13 files changed

+143
-58
lines changed

13 files changed

+143
-58
lines changed

src/LinearAlgebra.jl

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ StridedMatrixStride1{T} = StridedArrayStride1{T,2}
326326
"""
327327
LinearAlgebra.checksquare(A)
328328
329-
Check that a matrix is square, then return its common dimension.
329+
Checks whether a matrix is square, returning its common dimension if it is the case, or throwing a DimensionMismatch error otherwise.
330330
For multiple arguments, return a vector.
331331
332332
# Examples
@@ -340,19 +340,13 @@ julia> LinearAlgebra.checksquare(A, B)
340340
```
341341
"""
342342
function checksquare(A)
343-
m,n = size(A)
344-
m == n || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $(size(A))"))
345-
m
343+
sizeA = size(A)
344+
length(sizeA) == 2 || throw(DimensionMismatch(lazy"input is not a matrix: dimensions are $sizeA"))
345+
sizeA[1] == sizeA[2] || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $sizeA"))
346+
return sizeA[1]
346347
end
347348

348-
function checksquare(A...)
349-
sizes = Int[]
350-
for a in A
351-
size(a,1)==size(a,2) || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $(size(a))"))
352-
push!(sizes, size(a,1))
353-
end
354-
return sizes
355-
end
349+
checksquare(A...) = [checksquare(a) for a in A]
356350

357351
function char_uplo(uplo::Symbol)
358352
if uplo === :U

src/abstractq.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@ convert(::Type{AbstractQ{T}}, adjQ::AdjointQ) where {T} = convert(AbstractQ{T},
4242

4343
# ... to matrix
4444
Matrix{T}(Q::AbstractQ) where {T} = convert(Matrix{T}, Q*I) # generic fallback, yields square matrix
45-
Matrix{T}(adjQ::AdjointQ{S}) where {T,S} = convert(Matrix{T}, lmul!(adjQ, Matrix{S}(I, size(adjQ))))
4645
Matrix(Q::AbstractQ{T}) where {T} = Matrix{T}(Q)
4746
Array{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
4847
Array(Q::AbstractQ) = Matrix(Q)
48+
AbstractMatrix(Q::AbstractQ) = Q*I
49+
AbstractArray(Q::AbstractQ) = AbstractMatrix(Q)
50+
AbstractMatrix{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
51+
AbstractArray{T}(Q::AbstractQ) where {T} = AbstractMatrix{T}(Q)
4952
convert(::Type{T}, Q::AbstractQ) where {T<:AbstractArray} = T(Q)
5053
# legacy
5154
@deprecate(convert(::Type{AbstractMatrix{T}}, Q::AbstractQ) where {T},
@@ -172,10 +175,10 @@ qsize_check(Q::AbstractQ, P::AbstractQ) =
172175
# mimic the AbstractArray fallback
173176
*(Q::AbstractQ{<:Number}) = Q
174177

175-
(*)(Q::AbstractQ, J::UniformScaling) = Q*J.λ
176-
function (*)(Q::AbstractQ, b::Number)
177-
T = promote_type(eltype(Q), typeof(b))
178-
lmul!(convert(AbstractQ{T}, Q), Matrix{T}(b*I, size(Q)))
178+
(*)(Q::AbstractQ, b::Number) = Q*(b*I)
179+
function (*)(Q::AbstractQ, J::UniformScaling)
180+
T = promote_type(eltype(Q), eltype(J))
181+
lmul!(convert(AbstractQ{T}, Q), Matrix{T}(J, size(Q)))
179182
end
180183
function (*)(Q::AbstractQ, B::AbstractVector)
181184
T = promote_type(eltype(Q), eltype(B))
@@ -188,10 +191,10 @@ function (*)(Q::AbstractQ, B::AbstractMatrix)
188191
mul!(similar(B, T, (size(Q, 1), size(B, 2))), convert(AbstractQ{T}, Q), B)
189192
end
190193

191-
(*)(J::UniformScaling, Q::AbstractQ) = J.λ*Q
192-
function (*)(a::Number, Q::AbstractQ)
193-
T = promote_type(typeof(a), eltype(Q))
194-
rmul!(Matrix{T}(a*I, size(Q)), convert(AbstractQ{T}, Q))
194+
(*)(a::Number, Q::AbstractQ) = (a*I)*Q
195+
function (*)(J::UniformScaling, Q::AbstractQ)
196+
T = promote_type(eltype(J), eltype(Q))
197+
rmul!(Matrix{T}(J, size(Q)), convert(AbstractQ{T}, Q))
195198
end
196199
function (*)(A::AbstractVector, Q::AbstractQ)
197200
T = promote_type(eltype(A), eltype(Q))

src/blas.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,7 @@ end
21022102
her2k!(uplo, trans, alpha, A, B, beta, C)
21032103
21042104
Rank-2k update of the Hermitian matrix `C` as
2105-
`alpha*A*B' + alpha*B*A' + beta*C` or `alpha*A'*B + alpha*B'*A + beta*C`
2105+
`alpha*A*B' + alpha'*B*A' + beta*C` or `alpha*A'*B + alpha'*B'*A + beta*C`
21062106
according to [`trans`](@ref stdlib-blas-trans). The scalar `beta` has to be real.
21072107
Only the [`uplo`](@ref stdlib-blas-uplo) triangle of `C` is used. Return `C`.
21082108
"""
@@ -2111,8 +2111,8 @@ function her2k! end
21112111
"""
21122112
her2k(uplo, trans, alpha, A, B)
21132113
2114-
Return the [`uplo`](@ref stdlib-blas-uplo) triangle of `alpha*A*B' + alpha*B*A'`
2115-
or `alpha*A'*B + alpha*B'*A`, according to [`trans`](@ref stdlib-blas-trans).
2114+
Return the [`uplo`](@ref stdlib-blas-uplo) triangle of `alpha*A*B' + alpha'*B*A'`
2115+
or `alpha*A'*B + alpha'*B'*A`, according to [`trans`](@ref stdlib-blas-trans).
21162116
"""
21172117
her2k(uplo, trans, alpha, A, B)
21182118

src/bunchkaufman.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,12 @@ BunchKaufman{T}(B::BunchKaufman) where {T} =
217217
BunchKaufman(convert(Matrix{T}, B.LD), B.ipiv, B.uplo, B.symmetric, B.rook, B.info)
218218
Factorization{T}(B::BunchKaufman) where {T} = BunchKaufman{T}(B)
219219

220+
AbstractMatrix(B::BunchKaufman) = B.uplo == 'U' ? B.P'B.U*B.D*B.U'B.P : B.P'B.L*B.D*B.L'B.P
221+
AbstractArray(B::BunchKaufman) = AbstractMatrix(B)
222+
Matrix(B::BunchKaufman) = convert(Array, AbstractArray(B))
223+
Array(B::BunchKaufman) = Matrix(B)
224+
225+
220226
size(B::BunchKaufman) = size(getfield(B, :LD))
221227
size(B::BunchKaufman, d::Integer) = size(getfield(B, :LD), d)
222228
issymmetric(B::BunchKaufman) = B.symmetric

src/cholesky.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ Factorization{T}(C::CholeskyPivoted) where {T} = CholeskyPivoted{T}(C)
646646

647647
AbstractMatrix(C::Cholesky) = C.uplo == 'U' ? C.U'C.U : C.L*C.L'
648648
AbstractArray(C::Cholesky) = AbstractMatrix(C)
649-
Matrix(C::Cholesky) = Array(AbstractArray(C))
649+
Matrix(C::Cholesky) = convert(Array, AbstractArray(C))
650650
Array(C::Cholesky) = Matrix(C)
651651

652652
function AbstractMatrix(F::CholeskyPivoted)
@@ -655,7 +655,7 @@ function AbstractMatrix(F::CholeskyPivoted)
655655
U'U
656656
end
657657
AbstractArray(F::CholeskyPivoted) = AbstractMatrix(F)
658-
Matrix(F::CholeskyPivoted) = Array(AbstractArray(F))
658+
Matrix(F::CholeskyPivoted) = convert(Array, AbstractArray(F))
659659
Array(F::CholeskyPivoted) = Matrix(F)
660660

661661
copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo, C.info)

src/dense.jl

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -237,22 +237,14 @@ end
237237

238238
fillstored!(A::AbstractMatrix, v) = fill!(A, v)
239239

240-
diagind(m::Integer, n::Integer, k::Integer=0) = diagind(IndexLinear(), m, n, k)
241-
diagind(::IndexLinear, m::Integer, n::Integer, k::Integer=0) =
242-
k <= 0 ? range(1-k, step=m+1, length=min(m+k, n)) : range(k*m+1, step=m+1, length=min(m, n-k))
243-
244-
function diagind(::IndexCartesian, m::Integer, n::Integer, k::Integer=0)
245-
Cstart = CartesianIndex(1 + max(0,-k), 1 + max(0,k))
246-
Cstep = CartesianIndex(1, 1)
247-
length = max(0, k <= 0 ? min(m+k, n) : min(m, n-k))
248-
StepRangeLen(Cstart, Cstep, length)
249-
end
250-
251240
"""
252241
diagind(M::AbstractMatrix, k::Integer = 0, indstyle::IndexStyle = IndexLinear())
253242
diagind(M::AbstractMatrix, indstyle::IndexStyle = IndexLinear())
243+
diagind(::IndexStyle, m::Integer, n::Integer, k::Integer = 0)
244+
diagind(m::Integer, n::Integer, k::Integer = 0)
254245
255-
An `AbstractRange` giving the indices of the `k`th diagonal of the matrix `M`.
246+
An `AbstractRange` giving the indices of the `k`th diagonal of a matrix,
247+
specified either by the matrix `M` itself or by its dimensions `m` and `n`.
256248
Optionally, an index style may be specified which determines the type of the range returned.
257249
If `indstyle isa IndexLinear` (default), this returns an `AbstractRange{Integer}`.
258250
On the other hand, if `indstyle isa IndexCartesian`, this returns an `AbstractRange{CartesianIndex{2}}`.
@@ -262,6 +254,7 @@ If `k` is not provided, it is assumed to be `0` (corresponding to the main diago
262254
See also: [`diag`](@ref), [`diagm`](@ref), [`Diagonal`](@ref).
263255
264256
# Examples
257+
The matrix itself may be passed to `diagind`:
265258
```jldoctest
266259
julia> A = [1 2 3; 4 5 6; 7 8 9]
267260
3×3 Matrix{Int64}:
@@ -276,6 +269,18 @@ julia> diagind(A, IndexCartesian())
276269
StepRangeLen(CartesianIndex(1, 1), CartesianIndex(1, 1), 3)
277270
```
278271
272+
Alternatively, dimensions `m` and `n` may be passed to get the diagonal of an `m×n` matrix:
273+
```jldoctest
274+
julia> m, n = 5, 7
275+
(5, 7)
276+
277+
julia> diagind(m, n, 2)
278+
11:6:35
279+
280+
julia> diagind(IndexCartesian(), m, n)
281+
StepRangeLen(CartesianIndex(1, 1), CartesianIndex(1, 1), 5)
282+
```
283+
279284
!!! compat "Julia 1.11"
280285
Specifying an `IndexStyle` requires at least Julia 1.11.
281286
"""
@@ -286,6 +291,17 @@ end
286291

287292
diagind(A::AbstractMatrix, indexstyle::IndexStyle) = diagind(A, 0, indexstyle)
288293

294+
function diagind(::IndexCartesian, m::Integer, n::Integer, k::Integer=0)
295+
Cstart = CartesianIndex(1 + max(0,-k), 1 + max(0,k))
296+
Cstep = CartesianIndex(1, 1)
297+
length = max(0, k <= 0 ? min(m+k, n) : min(m, n-k))
298+
StepRangeLen(Cstart, Cstep, length)
299+
end
300+
301+
diagind(::IndexLinear, m::Integer, n::Integer, k::Integer=0) =
302+
k <= 0 ? range(1-k, step=m+1, length=min(m+k, n)) : range(k*m+1, step=m+1, length=min(m, n-k))
303+
diagind(m::Integer, n::Integer, k::Integer=0) = diagind(IndexLinear(), m, n, k)
304+
289305
"""
290306
diag(M, k::Integer=0)
291307

src/diagonal.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,23 @@ end
11111111
/(u::AdjointAbsVec, D::Diagonal) = (D' \ u')'
11121112
/(u::TransposeAbsVec, D::Diagonal) = transpose(transpose(D) \ transpose(u))
11131113

1114+
# norm
1115+
function generic_normMinusInf(D::Diagonal)
1116+
norm_diag = norm(D.diag, -Inf)
1117+
return size(D,1) > 1 ? min(norm_diag, zero(norm_diag)) : norm_diag
1118+
end
1119+
generic_normInf(D::Diagonal) = norm(D.diag, Inf)
1120+
generic_norm1(D::Diagonal) = norm(D.diag, 1)
1121+
generic_norm2(D::Diagonal) = norm(D.diag)
1122+
function generic_normp(D::Diagonal, p)
1123+
v = norm(D.diag, p)
1124+
if size(D,1) > 1 && p < 0
1125+
v = norm(zero(v), p)
1126+
end
1127+
return v
1128+
end
1129+
norm_x_minus_y(D1::Diagonal, D2::Diagonal) = norm_x_minus_y(D1.diag, D2.diag)
1130+
11141131
_opnorm1(A::Diagonal) = maximum(norm(x) for x in A.diag)
11151132
_opnormInf(A::Diagonal) = maximum(norm(x) for x in A.diag)
11161133
_opnorm12Inf(A::Diagonal, p) = maximum(opnorm(x, p) for x in A.diag)

src/eigen.jl

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ eigvecs(A::Union{Number, AbstractMatrix}; kws...) =
276276
eigvecs(F::Union{Eigen, GeneralizedEigen}) = F.vectors
277277

278278
eigvals(F::Union{Eigen, GeneralizedEigen}) = F.values
279+
eigmin(F::Union{Eigen, GeneralizedEigen}) = minimum(eigvals(F))
280+
eigmax(F::Union{Eigen, GeneralizedEigen}) = maximum(eigvals(F))
279281

280282
"""
281283
eigvals!(A; permute::Bool=true, scale::Bool=true, sortby) -> values
@@ -357,13 +359,8 @@ eigvals(x::Number; kwargs...) = imag(x) == 0 ? real(x) : x
357359
"""
358360
eigmax(A; permute::Bool=true, scale::Bool=true)
359361
360-
Return the largest eigenvalue of `A`.
361-
The option `permute=true` permutes the matrix to become
362-
closer to upper triangular, and `scale=true` scales the matrix by its diagonal elements to
363-
make rows and columns more equal in norm.
364-
Note that if the eigenvalues of `A` are complex,
365-
this method will fail, since complex numbers cannot
366-
be sorted.
362+
Return the largest eigenvalue of `A`, assuming they are all real, and throwing an error otherwise.
363+
The `permute` and `scale` keyword arguments are the same as for [`eigen`](@ref).
367364
368365
# Examples
369366
```jldoctest
@@ -388,23 +385,18 @@ Stacktrace:
388385
```
389386
"""
390387
function eigmax(A::Union{Number, AbstractMatrix}; permute::Bool=true, scale::Bool=true)
391-
v = eigvals(A, permute = permute, scale = scale)
388+
v = eigvals(A; permute, scale)
392389
if eltype(v)<:Complex
393390
throw(DomainError(A, "`A` cannot have complex eigenvalues."))
394391
end
395-
maximum(v)
392+
return maximum(v)
396393
end
397394

398395
"""
399396
eigmin(A; permute::Bool=true, scale::Bool=true)
400397
401-
Return the smallest eigenvalue of `A`.
402-
The option `permute=true` permutes the matrix to become
403-
closer to upper triangular, and `scale=true` scales the matrix by its diagonal elements to
404-
make rows and columns more equal in norm.
405-
Note that if the eigenvalues of `A` are complex,
406-
this method will fail, since complex numbers cannot
407-
be sorted.
398+
Return the smallest eigenvalue of `A`, assuming they are all real, and throwing an error otherwise.
399+
The `permute` and `scale` keyword arguments are the same as for [`eigen`](@ref).
408400
409401
# Examples
410402
```jldoctest
@@ -428,13 +420,12 @@ Stacktrace:
428420
[...]
429421
```
430422
"""
431-
function eigmin(A::Union{Number, AbstractMatrix};
432-
permute::Bool=true, scale::Bool=true)
433-
v = eigvals(A, permute = permute, scale = scale)
423+
function eigmin(A::Union{Number, AbstractMatrix}; permute::Bool=true, scale::Bool=true)
424+
v = eigvals(A; permute, scale)
434425
if eltype(v)<:Complex
435426
throw(DomainError(A, "`A` cannot have complex eigenvalues."))
436427
end
437-
minimum(v)
428+
return minimum(v)
438429
end
439430

440431
inv(A::Eigen) = A.vectors * inv(Diagonal(A.values)) / A.vectors

test/abstractq.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ n = 5
6868
end
6969
@test convert(Matrix, Q) Matrix(Q) Q[:,:] copyto!(zeros(T, size(Q)), Q) Q.Q*I
7070
@test convert(Matrix, Q') Matrix(Q') (Q')[:,:] copyto!(zeros(T, size(Q)), Q') Q.Q'*I
71+
@test AbstractMatrix(Q) AbstractArray(Q) AbstractMatrix{T}(Q) AbstractArray{T}(Q)
7172
@test Q[1,:] == Q.Q[1,:] == view(Q, 1, :)
7273
@test Q[:,1] == Q.Q[:,1] == view(Q, :, 1)
7374
@test Q[1,1] == Q.Q[1,1]

test/bunchkaufman.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,13 @@ end
259259
@test B.U * B.D * B.U' S
260260
end
261261

262+
@testset "BunchKaufman array constructors #1461" begin
263+
a = randn(5,5)
264+
A = a'a
265+
for ul in (:U, :L)
266+
B = bunchkaufman(Symmetric(A, ul))
267+
@test A Array(B) Matrix(B) AbstractArray(B) AbstractMatrix(B)
268+
end
269+
end
270+
262271
end # module TestBunchKaufman

0 commit comments

Comments
 (0)