From b3ee1deda2d75d28115ea3b74d6a9db95482d126 Mon Sep 17 00:00:00 2001 From: jishnub Date: Mon, 10 May 2021 22:48:10 +0400 Subject: [PATCH 1/3] specialize intersect for SingleValuedRange --- Project.toml | 2 +- src/SphericalHarmonicModes.jl | 19 +++++++++++++++++-- test/runtests.jl | 19 +++++++++++++++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index b5c07e5..ccce1b5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "SphericalHarmonicModes" uuid = "0e9554e2-b38b-11e9-16d7-9d9abfec665a" -version = "0.4.9" +version = "0.4.10" [compat] Aqua = "0.5" diff --git a/src/SphericalHarmonicModes.jl b/src/SphericalHarmonicModes.jl index 8fc5b74..9cdb551 100644 --- a/src/SphericalHarmonicModes.jl +++ b/src/SphericalHarmonicModes.jl @@ -369,6 +369,19 @@ Base.intersect(a::FullRange, b::T) where {T<:ZeroClampedRange} = T(min(a.l, b.l) Base.intersect(a::T, b::T) where {T<:ZeroClampedRange} = T(min(a.l, b.l)) Base.intersect(a::ZeroClampedRange, b::ZeroClampedRange) = ZeroTo(0) +function Base.intersect(a::SingleValuedRange, b::AbstractUnitRange{<:Integer}) + first(a) in b || return nothing + return a +end +Base.intersect(b::AbstractUnitRange{<:Integer}, a::SingleValuedRange) = intersect(a, b) +function Base.intersect(a::SingleValuedRange, b::SingleValuedRange) + first(a) == first(b) || return nothing + return a +end + +Base.intersect(a::SingleValuedRange, b::PartiallySpecifiedRange) = intersect(a, UnitRange(b)) +Base.intersect(a::PartiallySpecifiedRange, b::SingleValuedRange) = intersect(UnitRange(a), b) + for DT in [:LM, :ML] @eval function $DT(l_range::LT, ::Type{MT}) where {MT<:PartiallySpecifiedRange, LT<:AbstractUnitRange{<:Integer}} ensure_nonempty(l_range) @@ -424,6 +437,8 @@ true flip(m::LM) = ML(m) flip(m::ML) = LM(m) +Base.convert(::Type{T}, m::SHModeRange) where {T<:SHModeRange} = T(m) + function L2L1Triangle(l_min::Integer, l_max::Integer, mr::SHModeRange, args...) Δ = last(l_range(mr)) L2L1Triangle(l_min, l_max, Δ, args...) @@ -956,9 +971,9 @@ end for DT in [:LM, :ML] @eval function Base.intersect(mr1::$DT, mr2::$DT) - lr = intersect(l_range(mr1), l_range(mr2)) mr = intersect(m_range(mr1), m_range(mr2)) - (isempty(lr) || isempty(mr)) && return nothing + lr = intersect(l_range(mr1), l_range(mr2)) + (mr === nothing || lr === nothing || isempty(lr) || isempty(mr)) && return nothing $DT(lr, mr) end end diff --git a/test/runtests.jl b/test/runtests.jl index fbc4ab5..5496880 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -656,20 +656,24 @@ end @testset "LM" begin m = LM(0:1) @test ML(m) == ML(0:1) + @test convert(ML, m) == ML(0:1) @test flip(m) == ML(0:1) @test LM(m) === m + @test convert(LM, m) === m end @testset "ML" begin m = ML(0:1) @test LM(m) == LM(0:1) + @test convert(LM, m) == LM(0:1) @test flip(m) == LM(0:1) @test ML(m) === m + @test convert(ML, m) === m end end @testset "intersect" begin @testset "same l, different m" begin - for T in [LM,ML] + for T in [LM, ML] @eval begin l1 = $T(3:3,0:2) l2 = $T(3:3,1:3) @@ -697,7 +701,7 @@ end end end @testset "different l, same m" begin - for T in [LM,ML] + for T in [LM, ML] @eval begin l1 = $T(1:3,1:1) l2 = $T(1:1,1:1) @@ -746,6 +750,17 @@ end end @test intersect(FullRange(2), FullRange(1)) === FullRange(1) + + @test intersect(SingleValuedRange(1), -1:1) === SingleValuedRange(1) + @test intersect(SingleValuedRange(1), FullRange(1)) === SingleValuedRange(1) + @test intersect(SingleValuedRange(1), ZeroTo(1)) === SingleValuedRange(1) + @test intersect(SingleValuedRange(1), 2:3) === nothing + @test intersect(-1:1, SingleValuedRange(1)) === SingleValuedRange(1) + @test intersect(FullRange(1), SingleValuedRange(1)) === SingleValuedRange(1) + @test intersect(ZeroTo(1), SingleValuedRange(1)) === SingleValuedRange(1) + @test intersect(2:3, SingleValuedRange(1)) === nothing + @test intersect(SingleValuedRange(1), SingleValuedRange(1)) === SingleValuedRange(1) + @test intersect(SingleValuedRange(1), SingleValuedRange(2)) === nothing end @testset "show" begin From be435a9236f89ab3fa92359ac3eae4d05d896ba2 Mon Sep 17 00:00:00 2001 From: jishnub Date: Mon, 10 May 2021 23:14:57 +0400 Subject: [PATCH 2/3] fix convert --- src/SphericalHarmonicModes.jl | 28 +++++++++++++++++++++++++++- test/runtests.jl | 26 ++++++++++++++++++++------ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/SphericalHarmonicModes.jl b/src/SphericalHarmonicModes.jl index 9cdb551..c58af1c 100644 --- a/src/SphericalHarmonicModes.jl +++ b/src/SphericalHarmonicModes.jl @@ -149,6 +149,12 @@ for DT in [:LM, :ML] $DT{UnitRange{LI},typeof(m_range)}(UnitRange{LI}(l_range), m_range) end + + @eval function $DT{LT,MT}(m::SHModeRange) where {LT,MT} + lr = convert(LT, l_range(m)) + mr = convert(MT, m_range(m)) + $DT(lr, mr) + end end """ @@ -308,6 +314,11 @@ Base.last(x::SingleValuedRange) = x.n Base.length(x::SingleValuedRange) = 1 Base.show(io::IO, x::SingleValuedRange) = print(io, repr(x.n), ":", repr(x.n)) +function SingleValuedRange(r::AbstractUnitRange{<:Integer}) + length(r) == 1 || throw(ArgumentError("range must contain only one value")) + SingleValuedRange(first(r)) +end + """ ZeroTo(l::Int) @@ -326,6 +337,11 @@ Base.first(::ZeroTo) = 0 Base.last(r::ZeroTo) = r.l Base.show(io::IO, r::ZeroTo) = print(io, "0:", repr(r.l)) +function ZeroTo(r::AbstractUnitRange{<:Integer}) + first(r) == 0 || throw(ArgumentError("range must start at zero")) + ZeroTo(last(r)) +end + """ ToZero(l::Int) @@ -344,6 +360,11 @@ Base.first(r::ToZero) = -r.l Base.last(::ToZero) = 0 Base.show(io::IO, r::ToZero) = print(io,"-",repr(r.l),":0") +function ToZero(r::AbstractUnitRange{<:Integer}) + last(r) == 0 || throw(ArgumentError("range must end at zero")) + ToZero(-first(r)) +end + """ FullRange(l::Int) @@ -362,6 +383,11 @@ Base.first(r::FullRange) = -r.l Base.last(r::FullRange) = r.l Base.show(io::IO, r::FullRange) = print(io, repr(-r.l),":",repr(r.l)) +function FullRange(r::AbstractUnitRange{<:Integer}) + first(r) == -last(r) || throw(ArgumentError("starting value is not the negative of the ending value")) + FullRange(last(r)) +end + Base.intersect(a::FullRange, b::FullRange) = FullRange(min(maximum(a), maximum(b))) Base.intersect(a::T, b::FullRange) where {T<:ZeroClampedRange} = T(min(a.l, b.l)) Base.intersect(a::FullRange, b::T) where {T<:ZeroClampedRange} = T(min(a.l, b.l)) @@ -437,7 +463,7 @@ true flip(m::LM) = ML(m) flip(m::ML) = LM(m) -Base.convert(::Type{T}, m::SHModeRange) where {T<:SHModeRange} = T(m) +Base.convert(::Type{T}, m::SHModeRange) where {T<:SHModeRange} = m isa T ? m : T(m) function L2L1Triangle(l_min::Integer, l_max::Integer, mr::SHModeRange, args...) Δ = last(l_range(mr)) diff --git a/test/runtests.jl b/test/runtests.jl index 5496880..c0dbbaf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,24 +20,33 @@ end @test first(r) == 0 @test last(r) == 3 @test !isempty(r) + + r = ZeroTo(0:2) + @test first(r) == 0 + @test last(r) == 2 + @test_throws ArgumentError ZeroTo(1:2) end @testset "FullRange" begin r = FullRange(3) @test first(r) == -3 @test last(r) == 3 @test !isempty(r) - end - @testset "ZeroTo" begin - r = ZeroTo(3) - @test first(r) == 0 - @test last(r) == 3 - @test !isempty(r) + + r = FullRange(-1:1) + @test first(r) == -1 + @test last(r) == 1 + @test_throws ArgumentError FullRange(0:1) end @testset "ToZero" begin r = ToZero(3) @test first(r) == -3 @test last(r) == 0 @test !isempty(r) + + r = ToZero(-2:0) + @test first(r) == -2 + @test last(r) == 0 + @test_throws ArgumentError ToZero(-2:-1) end @testset "SingleValuedRange" begin n = 3 @@ -47,6 +56,11 @@ end @test last(r) == n @test length(r) == 1 @test !isempty(r) + + r = SingleValuedRange(n:n) + @test first(r) == n + @test last(r) == n + @test_throws ArgumentError SingleValuedRange(1:2) end end From 980a82243f1b1a84bef95821292fa79173f64f4f Mon Sep 17 00:00:00 2001 From: jishnub Date: Mon, 10 May 2021 23:36:13 +0400 Subject: [PATCH 3/3] don't add typed constructors --- src/SphericalHarmonicModes.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/SphericalHarmonicModes.jl b/src/SphericalHarmonicModes.jl index c58af1c..921fe04 100644 --- a/src/SphericalHarmonicModes.jl +++ b/src/SphericalHarmonicModes.jl @@ -149,12 +149,6 @@ for DT in [:LM, :ML] $DT{UnitRange{LI},typeof(m_range)}(UnitRange{LI}(l_range), m_range) end - - @eval function $DT{LT,MT}(m::SHModeRange) where {LT,MT} - lr = convert(LT, l_range(m)) - mr = convert(MT, m_range(m)) - $DT(lr, mr) - end end """