Skip to content

Commit

Permalink
Pass mutable copies to inplace LinearAlgebra functions (#52504)
Browse files Browse the repository at this point in the history
This gets some functions working with immutable matrix types, e.g.:
```julia
julia> using FillArrays, LinearAlgebra

julia> F = Fill(big(2), 4, 4)
4×4 Fill{BigInt}, with entries equal to 2

julia> det(F)
0

julia> triu(F)
4×4 Matrix{BigInt}:
 2  2  2  2
 0  2  2  2
 0  0  2  2
 0  0  0  2
```
  • Loading branch information
jishnub authored Dec 14, 2023
1 parent b9668ee commit 0ae2094
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 7 deletions.
10 changes: 5 additions & 5 deletions stdlib/LinearAlgebra/src/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ julia> triu(a)
0.0 0.0 0.0 1.0
```
"""
triu(M::AbstractMatrix) = triu!(copy(M))
triu(M::AbstractMatrix) = triu!(copymutable(M))

"""
tril(M)
Expand All @@ -362,7 +362,7 @@ julia> tril(a)
1.0 1.0 1.0 1.0
```
"""
tril(M::AbstractMatrix) = tril!(copy(M))
tril(M::AbstractMatrix) = tril!(copymutable(M))

"""
triu(M, k::Integer)
Expand Down Expand Up @@ -393,7 +393,7 @@ julia> triu(a,-3)
1.0 1.0 1.0 1.0
```
"""
triu(M::AbstractMatrix,k::Integer) = triu!(copy(M),k)
triu(M::AbstractMatrix,k::Integer) = triu!(copymutable(M),k)

"""
tril(M, k::Integer)
Expand Down Expand Up @@ -424,7 +424,7 @@ julia> tril(a,-3)
1.0 0.0 0.0 0.0
```
"""
tril(M::AbstractMatrix,k::Integer) = tril!(copy(M),k)
tril(M::AbstractMatrix,k::Integer) = tril!(copymutable(M),k)

"""
triu!(M)
Expand Down Expand Up @@ -1760,7 +1760,7 @@ Calculates the determinant of a matrix using the
[Bareiss Algorithm](https://en.wikipedia.org/wiki/Bareiss_algorithm).
Also refer to [`det_bareiss!`](@ref).
"""
det_bareiss(M) = det_bareiss!(copy(M))
det_bareiss(M) = det_bareiss!(copymutable(M))



Expand Down
20 changes: 18 additions & 2 deletions stdlib/LinearAlgebra/src/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,15 @@ function tril!(A::UpperTriangular{T}, k::Integer=0) where {T}
return UpperTriangular(tril!(A.data,k))
end
end
triu!(A::UpperTriangular, k::Integer=0) = UpperTriangular(triu!(A.data, k))
function triu!(A::UpperTriangular, k::Integer=0)
n = size(A,1)
if k > 0
for j in 1:n, i in max(1,j-k+1):j
A.data[i,j] = zero(eltype(A))
end
end
return A
end

function tril!(A::UnitUpperTriangular{T}, k::Integer=0) where {T}
n = size(A,1)
Expand Down Expand Up @@ -375,7 +383,15 @@ function triu!(A::LowerTriangular{T}, k::Integer=0) where {T}
end
end

tril!(A::LowerTriangular, k::Integer=0) = LowerTriangular(tril!(A.data, k))
function tril!(A::LowerTriangular, k::Integer=0)
n = size(A,1)
if k < 0
for j in 1:n, i in j:min(j-k-1,n)
A.data[i, j] = zero(eltype(A))
end
end
A
end

function triu!(A::UnitLowerTriangular{T}, k::Integer=0) where T
n = size(A,1)
Expand Down
13 changes: 13 additions & 0 deletions stdlib/LinearAlgebra/test/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ using .Main.OffsetArrays
isdefined(Main, :DualNumbers) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "DualNumbers.jl"))
using .Main.DualNumbers

isdefined(Main, :FillArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "FillArrays.jl"))
using .Main.FillArrays

Random.seed!(123)

n = 5 # should be odd
Expand Down Expand Up @@ -647,4 +650,14 @@ end
end
end

@testset "immutable arrays" begin
A = FillArrays.Fill(big(3), (4, 4))
M = Array(A)
@test triu(A) == triu(M)
@test triu(A, -1) == triu(M, -1)
@test tril(A) == tril(M)
@test tril(A, 1) == tril(M, 1)
@test det(A) == det(M)
end

end # module TestGeneric
2 changes: 2 additions & 0 deletions test/testhelpers/FillArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Fill(v, size::Vararg{Integer}) = Fill(v, size)

Base.size(F::Fill) = F.size

Base.copy(F::Fill) = F

@inline getindex_value(F::Fill) = F.value

@inline function Base.getindex(F::Fill{<:Any,N}, i::Vararg{Int,N}) where {N}
Expand Down

0 comments on commit 0ae2094

Please sign in to comment.