Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add LinearAlgebraExt #86

Merged
merged 10 commits into from
Aug 21, 2024
6 changes: 5 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseStaticArraysExt = "StaticArrays"
ConstructionBaseLinearAlgebraExt = "LinearAlgebra"

[compat]
IntervalSets = "0.5, 0.6, 0.7"
StaticArrays = "1"
julia = "1"
LinearAlgebra = "<0.0.1,1"

[extras]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[targets]
test = ["IntervalSets","StaticArrays","Test"]
test = ["IntervalSets","LinearAlgebra","StaticArrays","Test"]
51 changes: 51 additions & 0 deletions ext/ConstructionBaseLinearAlgebraExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module ConstructionBaseLinearAlgebraExt

if isdefined(Base, :get_extension)
import ConstructionBase
import LinearAlgebra
else
import ..ConstructionBase
import ..LinearAlgebra
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed?


### Tridiagonal

function tridiagonal_constructor(dl::V, d::V, du::V) where {V<:AbstractVector{T}} where T
LinearAlgebra.Tridiagonal{T,V}(dl, d, du)
end
function tridiagonal_constructor(dl::V, d::V, du::V, du2::V) where {V<:AbstractVector{T}} where T
LinearAlgebra.Tridiagonal{T,V}(dl, d, du, du2)
end

# `du2` may be undefined, so we need a custom `getfields` that checks `isdefined`
function ConstructionBase.getfields(o::LinearAlgebra.Tridiagonal)
if isdefined(o, :du2)
(dl=o.dl, d=o.d, du=o.du, du2=o.du2)
else
(dl=o.dl, d=o.d, du=o.du)
end
end

ConstructionBase.constructorof(::Type{<:LinearAlgebra.Tridiagonal}) = tridiagonal_constructor

### Cholesky

ConstructionBase.setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{()}) = C

function ConstructionBase.setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{(:L,),<:Tuple{<:LinearAlgebra.LowerTriangular}})
return LinearAlgebra.Cholesky(C.uplo === 'U' ? copy(patch.L.data') : patch.L.data, C.uplo, C.info)
end
function ConstructionBase.setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{(:U,),<:Tuple{<:LinearAlgebra.UpperTriangular}})
return LinearAlgebra.Cholesky(C.uplo === 'L' ? copy(patch.U.data') : patch.U.data, C.uplo, C.info)
end
function ConstructionBase.setproperties(
C::LinearAlgebra.Cholesky,
patch::NamedTuple{(:UL,),<:Tuple{<:Union{LinearAlgebra.LowerTriangular,LinearAlgebra.UpperTriangular}}}
)
return LinearAlgebra.Cholesky(patch.UL.data, C.uplo, C.info)
end
function ConstructionBase.setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple)
throw(ArgumentError("Invalid patch for `Cholesky`: $(patch)"))
end

end #module
39 changes: 4 additions & 35 deletions src/nonstandard.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using LinearAlgebra

### SubArray
# `offset1` and `stride1` fields are calculated from parent indices.
Expand Down Expand Up @@ -28,24 +27,7 @@ end
constructorof(::Type{<:PermutedDimsArray{<:Any,N,perm,iperm,<:Any}}) where {N,perm,iperm} =
PermutedDimsArrayConstructor{N,perm,iperm}()

### Tridiagonal
function tridiagonal_constructor(dl::V, d::V, du::V) where {V<:AbstractVector{T}} where T
Tridiagonal{T,V}(dl, d, du)
end
function tridiagonal_constructor(dl::V, d::V, du::V, du2::V) where {V<:AbstractVector{T}} where T
Tridiagonal{T,V}(dl, d, du, du2)
end

# `du2` may be undefined, so we need a custom `getfields` that checks `isdefined`
function getfields(o::Tridiagonal)
if isdefined(o, :du2)
(dl=o.dl, d=o.d, du=o.du, du2=o.du2)
else
(dl=o.dl, d=o.d, du=o.du)
end
end

constructorof(::Type{<:LinearAlgebra.Tridiagonal}) = tridiagonal_constructor

### LinRange
# `lendiv` is a calculated field
Expand All @@ -57,20 +39,7 @@ constructorof(::Type{<:LinRange}) = linrange_constructor
# ::Expr annotation is to make it type-stable on Julia 1.3-
constructorof(::Type{<:Expr}) = (head, args) -> Expr(head, args...)::Expr

### Cholesky
setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{()}) = C
function setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{(:L,),<:Tuple{<:LinearAlgebra.LowerTriangular}})
return LinearAlgebra.Cholesky(C.uplo === 'U' ? copy(patch.L.data') : patch.L.data, C.uplo, C.info)
end
function setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple{(:U,),<:Tuple{<:LinearAlgebra.UpperTriangular}})
return LinearAlgebra.Cholesky(C.uplo === 'L' ? copy(patch.U.data') : patch.U.data, C.uplo, C.info)
end
function setproperties(
C::LinearAlgebra.Cholesky,
patch::NamedTuple{(:UL,),<:Tuple{<:Union{LinearAlgebra.LowerTriangular,LinearAlgebra.UpperTriangular}}}
)
return LinearAlgebra.Cholesky(patch.UL.data, C.uplo, C.info)
end
function setproperties(C::LinearAlgebra.Cholesky, patch::NamedTuple)
throw(ArgumentError("Invalid patch for `Cholesky`: $(patch)"))
end
if !isdefined(Base,:get_extension)
using LinearAlgebra
include("../ext/ConstructionBaseLinearAlgebraExt.jl")
Copy link
Member

@aplavin aplavin Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using is not needed

end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to main source file?

10 changes: 9 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ end

@testset "getfields" begin
@test getfields(()) === ()
@test getfields([]) === NamedTuple()

#on julia 1.10 onwards, Array has fields :ref and :size. the :ref field is a memory field
#with non-constant value (the pointer location in memory). The only constant field in []
#is it's size, (0,)
if !isdefined(Base,:Memory)
@test getfields([]) === NamedTuple()
else
@test getfields([]).size === (0,)
longemen3000 marked this conversation as resolved.
Show resolved Hide resolved
end
@test getfields(Empty()) === NamedTuple()
@test getfields(NamedTuple()) === NamedTuple()
@test getfields((10,20,30)) === (10,20,30)
Expand Down
Loading