From cedd0f0f23624833e5473e75a285ac43b287bfbd Mon Sep 17 00:00:00 2001 From: singularitti Date: Tue, 12 Dec 2023 21:55:22 -0500 Subject: [PATCH 01/17] Rewrite broadcasting interface for `Lattice` --- src/lattice.jl | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/lattice.jl b/src/lattice.jl index 33e6c35..32cc238 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -176,5 +176,20 @@ Base.convert(::Type{Lattice{T}}, lattice::Lattice{S}) where {S,T} = Base.ndims(::Type{<:Lattice}) = 2 Base.ndims(::Lattice) = 2 -# See https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting -Base.broadcastable(lattice::Lattice) = Ref(lattice) +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L741 +Base.broadcastable(lattice::Lattice) = lattice + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L49 +Base.BroadcastStyle(::Type{<:Lattice}) = Broadcast.Style{Lattice}() + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L135 +Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, ::Broadcast.Style{Lattice}) = + Broadcast.Style{Lattice}() +Base.BroadcastStyle(::Broadcast.Style{Lattice}, ::Broadcast.AbstractArrayStyle{0}) = + Broadcast.Style{Lattice}() + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L315 +Broadcast.instantiate(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 +Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) From cb0986211e5afc708de64db910aef4cfd712a395 Mon Sep 17 00:00:00 2001 From: singularitti Date: Tue, 12 Dec 2023 21:59:44 -0500 Subject: [PATCH 02/17] Add "Test broadcasting" --- test/lattice.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/lattice.jl b/test/lattice.jl index a74cbc5..435c860 100644 --- a/test/lattice.jl +++ b/test/lattice.jl @@ -94,3 +94,15 @@ using Unitful, UnitfulAtomic @test inv(inv(lattice)) == lattice end end + +@testset "Test broadcasting" begin + lattice = Lattice([1, 0, 0], [0, 1, 0], [0, 0, 1]) + @test lattice .* 4 == 4 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) + @test lattice .* 4.0 == 4.0 .* lattice == Lattice([4.0, 0, 0], [0, 4.0, 0], [0, 0, 4.0]) + @test lattice .* 4//1 == 4//1 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) + @test lattice .* 1u"nm" == + 1u"nm" .* lattice == + Lattice( + [1u"nm", 0u"nm", 0u"nm"], [0u"nm", 1u"nm", 0u"nm"], [0u"nm", 0u"nm", 1u"nm"] + ) +end From 1db8f56112df7994b1fdc89872fc9326f56a6956 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 00:11:18 -0500 Subject: [PATCH 03/17] Remove unnecessary `Broadcast.instantiate` for `Broadcast.Broadcasted{Broadcast.Style{Lattice}}` Just use https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L305-L306 --- src/lattice.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lattice.jl b/src/lattice.jl index 32cc238..70ff7bf 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -188,8 +188,5 @@ Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, ::Broadcast.Style{Lattice Base.BroadcastStyle(::Broadcast.Style{Lattice}, ::Broadcast.AbstractArrayStyle{0}) = Broadcast.Style{Lattice}() -# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L315 -Broadcast.instantiate(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc - # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) From 5379849aa4dd9494f54edc733c24358b7b94616a Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 00:14:54 -0500 Subject: [PATCH 04/17] Remove 1 `Base.BroadcastStyle` No need to writing this binary broadcasting rule --- src/lattice.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lattice.jl b/src/lattice.jl index 70ff7bf..c7c68a7 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -183,10 +183,7 @@ Base.broadcastable(lattice::Lattice) = lattice Base.BroadcastStyle(::Type{<:Lattice}) = Broadcast.Style{Lattice}() # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L135 -Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, ::Broadcast.Style{Lattice}) = - Broadcast.Style{Lattice}() -Base.BroadcastStyle(::Broadcast.Style{Lattice}, ::Broadcast.AbstractArrayStyle{0}) = - Broadcast.Style{Lattice}() +Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{Lattice}) = b # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) From adcab225b7a4177ecb9fc7b16c76b38bd1e28ce7 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 00:21:33 -0500 Subject: [PATCH 05/17] Add operations with `Units` for `Lattice`s in ext/UnitfulExt.jl --- ext/UnitfulExt.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/UnitfulExt.jl b/ext/UnitfulExt.jl index 8200e1e..c03929b 100644 --- a/ext/UnitfulExt.jl +++ b/ext/UnitfulExt.jl @@ -37,4 +37,11 @@ uconvert(u::Units, lattice::ReciprocalLattice) = ustrip(lattice::Lattice) = Lattice(map(ustrip, parent(lattice))) ustrip(lattice::ReciprocalLattice) = ReciprocalLattice(map(ustrip, parent(lattice))) +# You need this to let the broadcasting work. +Base.:*(lattice::Lattice, unit::Units) = Lattice(parent(lattice) * unit) +Base.:*(unit::Units, lattice::Lattice) = lattice * unit + +# You need this to let the broadcasting work. +Base.:/(lattice::Lattice, unit::Units) = Lattice(parent(lattice) / unit) + end From f504a2cb4c96b7387c1d98ecaba5da37e035d666 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 01:42:15 -0500 Subject: [PATCH 06/17] Fix `copy` for `Broadcast.Broadcasted{Broadcast.Style{Lattice},A,F,Tuple{Lattice{Int64}}}` for uniary & binary functions --- src/lattice.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lattice.jl b/src/lattice.jl index c7c68a7..45521c4 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -186,4 +186,9 @@ Base.BroadcastStyle(::Type{<:Lattice}) = Broadcast.Style{Lattice}() Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{Lattice}) = b # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 -Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) +function Base.copy( + bc::Broadcast.Broadcasted{Broadcast.Style{Lattice},A,F,Tuple{Lattice{Int64}}} +) where {A,F} + return Lattice(bc.f.(x for x in bc)) +end # For uniary functions +Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) # For binary functions From 1fbe739c043a1016d72009db2f43e989a158d3f4 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 01:45:17 -0500 Subject: [PATCH 07/17] Simplify `copy` for `Broadcast.Broadcasted{Broadcast.Style{Lattice},A,F,Tuple{Lattice{Int64}}}` for uniary & binary functions using `getindex` for `Broadcast.Broadcasted` --- src/lattice.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lattice.jl b/src/lattice.jl index 45521c4..25c8d77 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -186,9 +186,5 @@ Base.BroadcastStyle(::Type{<:Lattice}) = Broadcast.Style{Lattice}() Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{Lattice}) = b # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 -function Base.copy( - bc::Broadcast.Broadcasted{Broadcast.Style{Lattice},A,F,Tuple{Lattice{Int64}}} -) where {A,F} - return Lattice(bc.f.(x for x in bc)) -end # For uniary functions -Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = bc.f(bc.args...) # For binary functions +Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = + Lattice(bc.f.(x for x in bc)) # For uniary and binary functions From d326c051709d873e0ea9745aabfb4a711751a239 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 01:52:05 -0500 Subject: [PATCH 08/17] Update "Test broadcasting" with units --- test/lattice.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/lattice.jl b/test/lattice.jl index 435c860..21bd790 100644 --- a/test/lattice.jl +++ b/test/lattice.jl @@ -100,6 +100,11 @@ end @test lattice .* 4 == 4 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) @test lattice .* 4.0 == 4.0 .* lattice == Lattice([4.0, 0, 0], [0, 4.0, 0], [0, 0, 4.0]) @test lattice .* 4//1 == 4//1 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) + @test lattice .* u"nm" == + u"nm" .* lattice == + Lattice( + [1u"nm", 0u"nm", 0u"nm"], [0u"nm", 1u"nm", 0u"nm"], [0u"nm", 0u"nm", 1u"nm"] + ) @test lattice .* 1u"nm" == 1u"nm" .* lattice == Lattice( From aac5ad039a00a82a5e814b5831607db0be3dab27 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:03:40 -0500 Subject: [PATCH 09/17] Add test for `./` --- test/lattice.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lattice.jl b/test/lattice.jl index 21bd790..ffe76a7 100644 --- a/test/lattice.jl +++ b/test/lattice.jl @@ -100,6 +100,7 @@ end @test lattice .* 4 == 4 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) @test lattice .* 4.0 == 4.0 .* lattice == Lattice([4.0, 0, 0], [0, 4.0, 0], [0, 0, 4.0]) @test lattice .* 4//1 == 4//1 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) + @test lattice ./ 4 == Lattice([1//4, 0, 0], [0, 1//4, 0], [0, 0, 1//4]) @test lattice .* u"nm" == u"nm" .* lattice == Lattice( From 4de2c597cf26fc7e4b6718bd57907e399f9b0453 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:04:00 -0500 Subject: [PATCH 10/17] Fix `copy` for `Broadcast.Broadcasted{Broadcast.Style{Lattice},A,F,Tuple{Lattice{Int64}}}` for uniary & binary functions again --- src/lattice.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lattice.jl b/src/lattice.jl index 25c8d77..419a07d 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -186,5 +186,4 @@ Base.BroadcastStyle(::Type{<:Lattice}) = Broadcast.Style{Lattice}() Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{Lattice}) = b # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 -Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = - Lattice(bc.f.(x for x in bc)) # For uniary and binary functions +Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = Lattice(x for x in bc) # For uniary and binary functions From 726a501a7b4c0ca6a06e15a300336ef916017930 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:19:24 -0500 Subject: [PATCH 11/17] Ban `Number` divided by `Lattice` explicitly --- src/lattice.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lattice.jl b/src/lattice.jl index 419a07d..d2ce9ca 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -157,6 +157,8 @@ Base.:*(x::Number, lattice::Lattice) = lattice * x # You need this to let the broadcasting work. Base.:/(lattice::Lattice, x::Number) = Lattice(parent(lattice) / x) +Base.:/(::Number, ::Lattice) = + throw(ArgumentError("you cannot divide a number by a lattice!")) Base.:+(lattice::Lattice) = lattice # You need this to let the broadcasting work. From a6b959c69e558e286da6b9c7ba6a800d76f7c922 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:19:35 -0500 Subject: [PATCH 12/17] Ban broadcasting `Number` divided by `Lattice` explicitly --- src/lattice.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lattice.jl b/src/lattice.jl index d2ce9ca..8e24362 100644 --- a/src/lattice.jl +++ b/src/lattice.jl @@ -189,3 +189,6 @@ Base.BroadcastStyle(::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{Lattic # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{Lattice}}) = Lattice(x for x in bc) # For uniary and binary functions + +Base.broadcasted(::typeof(/), ::Number, ::Lattice) = + throw(ArgumentError("you cannot divide a number by a lattice!")) From 01f62aef747fe8dbc9ade456472a6e8e82f67251 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:20:18 -0500 Subject: [PATCH 13/17] Add `Number` constraints to `+` `-` to `ReciprocalLattice`s --- src/reciprocal.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reciprocal.jl b/src/reciprocal.jl index 4cf8297..f47f231 100644 --- a/src/reciprocal.jl +++ b/src/reciprocal.jl @@ -78,11 +78,11 @@ Base.firstindex(::ReciprocalLattice) = 1 Base.lastindex(::ReciprocalLattice) = 9 # You need this to let the broadcasting work. -Base.:*(lattice::ReciprocalLattice, x) = ReciprocalLattice(parent(lattice) * x) -Base.:*(x, lattice::ReciprocalLattice) = lattice * x +Base.:*(lattice::ReciprocalLattice, x::Number) = ReciprocalLattice(parent(lattice) * x) +Base.:*(x::Number, lattice::ReciprocalLattice) = lattice * x # You need this to let the broadcasting work. -Base.:/(lattice::ReciprocalLattice, x) = ReciprocalLattice(parent(lattice) / x) +Base.:/(lattice::ReciprocalLattice, x::Number) = ReciprocalLattice(parent(lattice) / x) Base.:+(lattice::ReciprocalLattice) = lattice From c0d187cf93a76da8959f9da5be99ca63070f1352 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:21:08 -0500 Subject: [PATCH 14/17] Fix broadcasting interface for `ReciprocalLattice`s --- src/reciprocal.jl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/reciprocal.jl b/src/reciprocal.jl index f47f231..b376558 100644 --- a/src/reciprocal.jl +++ b/src/reciprocal.jl @@ -97,5 +97,17 @@ Base.convert(::Type{ReciprocalLattice{T}}, lattice::ReciprocalLattice{S}) where Base.ndims(::Type{<:ReciprocalLattice}) = 2 Base.ndims(::ReciprocalLattice) = 2 -# See https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting -Base.broadcastable(lattice::ReciprocalLattice) = Ref(lattice) +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L741 +Base.broadcastable(lattice::ReciprocalLattice) = lattice + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L49 +Base.BroadcastStyle(::Type{<:ReciprocalLattice}) = Broadcast.Style{ReciprocalLattice}() + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L135 +Base.BroadcastStyle( + ::Broadcast.AbstractArrayStyle{0}, b::Broadcast.Style{ReciprocalLattice} +) = b + +# See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 +Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{ReciprocalLattice}}) = + ReciprocalLattice(MMatrix{3,3}(x for x in bc)) # For uniary and binary functions From ed2673795b4a5143a44471b1736537ab0747c52c Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:21:35 -0500 Subject: [PATCH 15/17] Ban `Number` divided by `Lattice` explicitly --- src/reciprocal.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/reciprocal.jl b/src/reciprocal.jl index b376558..5872251 100644 --- a/src/reciprocal.jl +++ b/src/reciprocal.jl @@ -83,6 +83,8 @@ Base.:*(x::Number, lattice::ReciprocalLattice) = lattice * x # You need this to let the broadcasting work. Base.:/(lattice::ReciprocalLattice, x::Number) = ReciprocalLattice(parent(lattice) / x) +Base.:/(::Number, ::ReciprocalLattice) = + throw(ArgumentError("you cannot divide a number by a reciprocal lattice!")) Base.:+(lattice::ReciprocalLattice) = lattice From aabfc30aeb33e1036a718fd42216424d9ada2a22 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:22:32 -0500 Subject: [PATCH 16/17] Ban broadcasting `Number` divided by `ReciprocalLattice` explicitly --- src/reciprocal.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/reciprocal.jl b/src/reciprocal.jl index 5872251..72882b2 100644 --- a/src/reciprocal.jl +++ b/src/reciprocal.jl @@ -113,3 +113,6 @@ Base.BroadcastStyle( # See https://github.com/JuliaLang/julia/blob/v1.10.0-rc2/base/broadcast.jl#L1114-L1119 Base.copy(bc::Broadcast.Broadcasted{Broadcast.Style{ReciprocalLattice}}) = ReciprocalLattice(MMatrix{3,3}(x for x in bc)) # For uniary and binary functions + +Base.broadcasted(::typeof(/), ::Number, ::ReciprocalLattice) = + throw(ArgumentError("you cannot divide a number by a reciprocal lattice!")) From aacf9f3614970295b7b93e90c583b87c10ea0092 Mon Sep 17 00:00:00 2001 From: singularitti Date: Wed, 13 Dec 2023 02:23:13 -0500 Subject: [PATCH 17/17] Add "Test broadcasting for reciprocal lattices" --- test/lattice.jl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/lattice.jl b/test/lattice.jl index ffe76a7..b442851 100644 --- a/test/lattice.jl +++ b/test/lattice.jl @@ -95,7 +95,7 @@ using Unitful, UnitfulAtomic end end -@testset "Test broadcasting" begin +@testset "Test broadcasting for lattices" begin lattice = Lattice([1, 0, 0], [0, 1, 0], [0, 0, 1]) @test lattice .* 4 == 4 .* lattice == Lattice([4, 0, 0], [0, 4, 0], [0, 0, 4]) @test lattice .* 4.0 == 4.0 .* lattice == Lattice([4.0, 0, 0], [0, 4.0, 0], [0, 0, 4.0]) @@ -111,4 +111,14 @@ end Lattice( [1u"nm", 0u"nm", 0u"nm"], [0u"nm", 1u"nm", 0u"nm"], [0u"nm", 0u"nm", 1u"nm"] ) + @test_throws ArgumentError 4 / lattice + @test_throws ArgumentError 4.0 ./ lattice +end + +@testset "Test broadcasting for reciprocal lattices" begin + a, b, c = 4, 3, 5 + lattice = Lattice([a, -b, 0] / 2, [a, b, 0] / 2, [0, 0, c]) + @test reciprocal(lattice .* 4) == reciprocal(lattice) ./ 4 + @test_throws ArgumentError 4 / reciprocal(lattice) + @test_throws ArgumentError 4.0 ./ reciprocal(lattice) end