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 intervalsets and staticarrays support #69

Merged
merged 4 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
name = "ConstructionBase"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
authors = ["Takafumi Arakaki", "Rafael Schouten", "Jan Weidner"]
version = "1.4.1"
version = "1.5.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[extensions]
IntervalSetsExt = "IntervalSets"
StaticArraysExt = "StaticArrays"

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

[extras]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

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

using ConstructionBase
using IntervalSets

ConstructionBase.constructorof(::Type{<:Interval{L, R}}) where {L, R} = Interval{L, R}

end
31 changes: 31 additions & 0 deletions ext/StaticArraysExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module StaticArraysExt

using ConstructionBase
using StaticArrays

# general static arrays need to keep the size parameter
ConstructionBase.constructorof(sa::Type{<:SArray{S}}) where {S} = SArray{S}
ConstructionBase.constructorof(sa::Type{<:MArray{S}}) where {S} = MArray{S}
ConstructionBase.constructorof(sa::Type{<:SizedArray{S}}) where {S} = SizedArray{S}

# static vectors don't even need the explicit size specification
ConstructionBase.constructorof(::Type{<:SVector}) = SVector
ConstructionBase.constructorof(::Type{<:MVector}) = MVector

# set properties by name: x, y, z, w
@generated function ConstructionBase.setproperties(obj::Union{SVector{N}, MVector{N}}, patch::NamedTuple{KS}) where {N, KS}
if KS == (:data,)
:( constructorof(typeof(obj))(only(patch)) )
else
N <= 4 || error("type $obj does not have properties $(join(KS, ", "))")
propnames = (:x, :y, :z, :w)[1:N]
aplavin marked this conversation as resolved.
Show resolved Hide resolved
KS ⊆ propnames || error("type $obj does not have properties $(join(KS, ", "))")
field_exprs = map(enumerate(propnames)) do (i, p)
from = p ∈ KS ? :patch : :obj
:( $from.$p )
end
:( constructorof(typeof(obj))($(field_exprs...)) )
end
end

end
46 changes: 46 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,49 @@ end
@inferred getproperties(funny_numbers(S,20))
@inferred getproperties(funny_numbers(S,40))
end


using StaticArrays, IntervalSets

if isdefined(Base, :get_extension) # some 1.9 version
@testset "staticarrays" begin
sa = @SVector [2, 4, 6, 8]
sa2 = ConstructionBase.constructorof(typeof(sa))((3.0, 5.0, 7.0, 9.0))
@test sa2 === @SVector [3.0, 5.0, 7.0, 9.0]

ma = @MMatrix [2.0 4.0; 6.0 8.0]
ma2 = @inferred ConstructionBase.constructorof(typeof(ma))((1, 2, 3, 4))
@test ma2 isa MArray{Tuple{2,2},Int,2,4}
@test all(ma2 .=== @MMatrix [1 3; 2 4])

sz = SizedArray{Tuple{2,2}}([1 2;3 4])
sz2 = @inferred ConstructionBase.constructorof(typeof(sz))([:a :b; :c :d])
@test sz2 == SizedArray{Tuple{2,2}}([:a :b; :c :d])
@test typeof(sz2) <: SizedArray{Tuple{2,2},Symbol,2,2}

for T in (SVector, MVector)
@test @inferred(ConstructionBase.constructorof(T)((1, 2, 3)))::T == T((1, 2, 3))
@test @inferred(ConstructionBase.constructorof(T{3})((1, 2, 3)))::T == T((1, 2, 3))
@test @inferred(ConstructionBase.constructorof(T{3})((1, 2)))::T == T((1, 2))
@test @inferred(ConstructionBase.constructorof(T{3, Symbol})((1, 2, 3)))::T == T((1, 2, 3))
@test @inferred(ConstructionBase.constructorof(T{3, Symbol})((1, 2)))::T == T((1, 2))
@test @inferred(ConstructionBase.constructorof(T{3, X} where {X})((1, 2, 3)))::T == T((1, 2, 3))
@test @inferred(ConstructionBase.constructorof(T{3, X} where {X})((1, 2)))::T == T((1, 2))
@test @inferred(ConstructionBase.constructorof(T{X, Symbol} where {X})((1, 2, 3)))::T == T((1, 2, 3))
end

sv = SVector(1, 2)
@test SVector(3.0, 2.0) === @inferred setproperties(sv, x = 3.0)
@test SVector(3.0, 5.0) === @inferred setproperties(sv, x = 3.0, y = 5.0)
@test SVector(-1.0, -2.0) === @inferred setproperties(sv, data = (-1.0, -2))
@test_throws "does not have properties z" setproperties(sv, z = 3.0)
@test_throws "does not have properties z" setproperties(SVector(1, 2, 3, 4, 5), z = 3.0)
end

@testset "intervalsets" begin
@test constructorof(typeof(1..2))(0.5, 1.5) === 0.5..1.5
@test constructorof(typeof(OpenInterval(1, 2)))(0.5, 1.5) === OpenInterval(0.5, 1.5)
@test setproperties(1..2, left=0.0) === 0.0..2.0
@test setproperties(OpenInterval(1.0, 2.0), left=1, right=5) === OpenInterval(1, 5)
end
end