diff --git a/Project.toml b/Project.toml index 0d75506b..802ff1cb 100644 --- a/Project.toml +++ b/Project.toml @@ -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" diff --git a/src/FillArrays.jl b/src/FillArrays.jl index 2cc63b8d..2229f24f 100644 --- a/src/FillArrays.jl +++ b/src/FillArrays.jl @@ -625,6 +625,8 @@ include("fillalgebra.jl") include("fillbroadcast.jl") include("trues.jl") +include("glue.jl") + ## # print ## diff --git a/src/fillalgebra.jl b/src/fillalgebra.jl index 800e803a..31ef5fe2 100644 --- a/src/fillalgebra.jl +++ b/src/fillalgebra.jl @@ -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)] @@ -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 #### diff --git a/src/glue.jl b/src/glue.jl new file mode 100644 index 00000000..d1009f36 --- /dev/null +++ b/src/glue.jl @@ -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 \ No newline at end of file diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..f97bf14c --- /dev/null +++ b/test/Project.toml @@ -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" diff --git a/test/runtests.jl b/test/runtests.jl index 5a213f6b..a8546a37 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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 @@ -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 @@ -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)