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

generalise Zero/Fill +/- using Requires.jl #239

Closed
wants to merge 7 commits into from
Closed
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
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ version = "0.13.11"
[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[compat]
Aqua = "0.5"
Requires = "1.0"
julia = "1.6"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

Expand Down
2 changes: 2 additions & 0 deletions src/FillArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,8 @@ include("fillalgebra.jl")
include("fillbroadcast.jl")
include("trues.jl")

include("glue.jl")

##
# print
##
Expand Down
74 changes: 40 additions & 34 deletions src/fillalgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,45 +215,38 @@ end
-(a::Zeros) = a
-(a::AbstractFill) = Fill(-getindex_value(a), size(a))


function +(a::Zeros{T}, b::Zeros{V}) where {T, V} # for disambiguity
promote_shape(a,b)
return elconvert(promote_op(+,T,V),a)
end
# no AbstractArray. Otherwise incompatible with StaticArrays.jl
# AbstractFill for disambiguity
for TYPE in (:Array, :AbstractFill, :AbstractRange, :Diagonal)
@eval function +(a::$TYPE{T}, b::Zeros{V}) where {T, V}
promote_shape(a,b)
return elconvert(promote_op(+,T,V),a)
end
@eval +(a::Zeros, b::$TYPE) = b + a
# templates
macro _add_zero(TYPE)
esc(quote
@inline +(a::$TYPE, b::Zeros) = abs_add_zero(a, b)
@inline -(a::$TYPE, b::Zeros) = abs_add_zero(a, b)
@inline +(a::Zeros, b::$TYPE) = abs_add_zero(b, a)
@inline -(a::Zeros, b::$TYPE) = abs_add_zero(-b, a)
end)
end

# for VERSION other than 1.6, could use ZerosMatrix only
function +(a::AbstractFillMatrix{T}, b::UniformScaling) where {T}
n = checksquare(a)
return a + Diagonal(Fill(zero(T) + b.λ, n))
end

# LinearAlgebra defines `-(a::AbstractMatrix, b::UniformScaling) = a + (-b)`,
# so the implementation of `-(a::UniformScaling, b::AbstractFill{<:Any,2})` is sufficient
-(a::UniformScaling, b::AbstractFill) = -b + a # @test I-Zeros(3,3) === Diagonal(Ones(3))

-(a::Ones, b::Ones) = Zeros(a) + Zeros(b)

# no AbstractArray. Otherwise incompatible with StaticArrays.jl
for TYPE in (:Array, :AbstractRange)
@eval begin
+(a::$TYPE, b::AbstractFill) = fill_add(a, b)
-(a::$TYPE, b::AbstractFill) = a + (-b)
+(a::AbstractFill, b::$TYPE) = fill_add(b, a)
-(a::AbstractFill, b::$TYPE) = a + (-b)
end
macro _add_fill(TYPE)
esc(quote
@_add_zero $TYPE
@inline +(a::$TYPE, b::AbstractFill) = fill_add(a, b)
@inline -(a::$TYPE, b::AbstractFill) = fill_add(a, -b)
@inline +(a::AbstractFill, b::$TYPE) = fill_add(b, a)
@inline -(a::AbstractFill, b::$TYPE) = fill_add(-b, a)
end)
end
+(a::Zeros, b::Zeros) = abs_add_zero(a, b)
-(a::Zeros, b::Zeros) = abs_add_zero(a, b)
+(a::AbstractFill, b::AbstractFill) = Fill(getindex_value(a) + getindex_value(b), promote_shape(a,b))
-(a::AbstractFill, b::AbstractFill) = a + (-b)

@_add_zero AbstractFill
@_add_fill AbstractArray
@_add_fill AbstractRange

# backends
@inline function abs_add_zero(a::AbstractArray{T}, b::Zeros{V}) where {T, V}
promote_shape(a,b)
return elconvert(promote_op(+,T,V),a)
end
@inline function fill_add(a::AbstractArray, b::AbstractFill)
promote_shape(a, b)
a .+ [getindex_value(b)]
Expand All @@ -268,6 +261,19 @@ end
@inline elconvert(::Type{T}, A::AbstractUnitRange) where T<:Integer = AbstractUnitRange{T}(A)
@inline elconvert(::Type{T}, A::AbstractArray) where T = AbstractArray{T}(A)

# special cases
# for VERSION other than 1.6, could use ZerosMatrix only
function +(a::AbstractFillMatrix{T}, b::UniformScaling) where {T}
n = checksquare(a)
return a + Diagonal(Fill(zero(T) + b.λ, n))
end

# LinearAlgebra defines `-(a::AbstractMatrix, b::UniformScaling) = a + (-b)`,
# so the implementation of `-(a::UniformScaling, b::AbstractFill{<:Any,2})` is sufficient
-(a::UniformScaling, b::AbstractFill) = -b + a # @test I-Zeros(3,3) === Diagonal(Ones(3))

-(a::Ones, b::Ones) = Zeros(a) + Zeros(b)

####
# norm
####
Expand Down
10 changes: 10 additions & 0 deletions src/glue.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Requires

function __init__()
@require StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" begin
@_add_fill StaticArrays.StaticArray
end
@require LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02" begin
@_add_fill LazyArrays.Vcat
end
end
10 changes: 10 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
13 changes: 8 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using FillArrays, LinearAlgebra, SparseArrays, StaticArrays, Random, Base64, Test, Statistics
using FillArrays, LinearAlgebra, SparseArrays, StaticArrays, Random, Base64, Test, Statistics, LazyArrays
import FillArrays: AbstractFill, RectDiagonal, SquareEye

using Aqua
Expand Down Expand Up @@ -311,16 +311,16 @@ as_array(x::UniformScaling) = x
function test_addition_and_subtraction(As, Bs, Tout::Type)
for A in As, B in Bs
@testset "$(typeof(A)) ± $(typeof(B))" begin
@test A + B isa Tout{promote_type(eltype(A), eltype(B))}
@test typeof(A + B) <: Tout{promote_type(eltype(A), eltype(B))}
@test as_array(A + B) == as_array(A) + as_array(B)

@test A - B isa Tout{promote_type(eltype(A), eltype(B))}
@test typeof(A - B) <: Tout{promote_type(eltype(A), eltype(B))}
@test as_array(A - B) == as_array(A) - as_array(B)

@test B + A isa Tout{promote_type(eltype(B), eltype(A))}
@test typeof(B + A) <: Tout{promote_type(eltype(B), eltype(A))}
@test as_array(B + A) == as_array(B) + as_array(A)

@test B - A isa Tout{promote_type(eltype(B), eltype(A))}
@test typeof(B - A) <: Tout{promote_type(eltype(B), eltype(A))}
@test as_array(B - A) == as_array(B) - as_array(A)
end
end
Expand Down Expand Up @@ -378,6 +378,9 @@ end
A_svec, B_svec = SVector{5}(rand(5)), SVector(1, 2, 3, 4, 5)
test_addition_and_subtraction((A_fill, B_fill, Zeros(5)), (A_svec, B_svec), SVector{5})

# FillArray + LazyArray should not have ambiguities
test_addition_and_subtraction((A_fill, B_fill, Zeros(5)), (Vcat(1:2, 1:3),), Vcat)

# Issue #224
A_matmat, B_matmat = Fill(rand(3,3),5), [rand(3,3) for n=1:5]
test_addition_and_subtraction((A_matmat,), (A_matmat,), Fill)
Expand Down