diff --git a/Project.toml b/Project.toml index d0d3e60..2b68433 100644 --- a/Project.toml +++ b/Project.toml @@ -3,6 +3,7 @@ uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" version = "1.14.0" [deps] +EltypeExtensions = "583f92f5-06d6-4306-8236-316410defc98" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" @@ -21,6 +22,7 @@ FillArraysStatisticsExt = "Statistics" [compat] Aqua = "0.8" Documenter = "1" +EltypeExtensions = "0.1.1" Infinities = "0.1" LinearAlgebra = "1.6" PDMats = "0.11.17" diff --git a/src/FillArrays.jl b/src/FillArrays.jl index 66dad48..ee875a1 100644 --- a/src/FillArrays.jl +++ b/src/FillArrays.jl @@ -15,6 +15,7 @@ import LinearAlgebra: rank, svdvals!, tril, triu, tril!, triu!, diag, transpose, import Base.Broadcast: broadcasted, DefaultArrayStyle, broadcast_shape, BroadcastStyle, Broadcasted +import EltypeExtensions: convert_eltype, _to_eltype export Zeros, Ones, Fill, Eye, Trues, Falses, OneElement @@ -137,6 +138,8 @@ Fill{T,0}(x, ::Tuple{}) where T = Fill{T,0,Tuple{}}(convert(T, x)::T, ()) # ambi """ `Fill(x, dims)` construct lazy version of `fill(x, dims)` """ @inline Fill(x::T, sz::Tuple{Vararg{Any,N}}) where {T, N} = Fill{T, N}(x, sz) +_to_eltype(::Type{T}, ::Type{Fill{V,N,Axes}}) where {T,V,N,Axes} = Fill{T,N,Axes} + # We restrict to when T is specified to avoid ambiguity with a Fill of a Fill @inline Fill{T}(F::Fill{T}) where T = F @inline Fill{T,N}(F::Fill{T,N}) where {T,N} = F @@ -340,6 +343,7 @@ for (AbsTyp, Typ, funcs, func) in ((:AbstractZeros, :Zeros, :zeros, :zero), (:Ab getindex(F::$AbsTyp{T,0}) where T = getindex_value(F) promote_rule(::Type{$Typ{T, N, Axes}}, ::Type{$Typ{V, N, Axes}}) where {T,V,N,Axes} = $Typ{promote_type(T,V),N,Axes} + _to_eltype(::Type{T}, ::Type{$Typ{V,N,Axes}}) where {T,V,N,Axes} = $Typ{T,N,Axes} function convert(::Type{Typ}, A::$AbsTyp{V,N,Axes}) where {T,V,N,Axes,Typ<:$AbsTyp{T,N,Axes}} convert(T, getindex_value(A)) # checks that the types are convertible Typ(axes(A)) diff --git a/src/fillalgebra.jl b/src/fillalgebra.jl index f98ae60..2f42420 100644 --- a/src/fillalgebra.jl +++ b/src/fillalgebra.jl @@ -434,14 +434,16 @@ Base.reduce_first(::typeof(+), x::AbstractOnes) = Fill(Base.reduce_first(+, geti function +(a::AbstractZeros{T}, b::AbstractZeros{V}) where {T, V} # for disambiguity promote_shape(a,b) - return elconvert(promote_op(+,T,V),a) + return convert_eltype(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::AbstractZeros{V}) where {T, V} promote_shape(a,b) - return elconvert(promote_op(+,T,V),a) + ret = convert_eltype(promote_op(+,T,V), a) + ret ≡ a ? copy(ret) : ret # must return a copy + # (_to_eltype(promote_op(+,T,V), typeof(a)))(a) doesn't work for types not supporting such constructors. E.g. https://github.com/JuliaLang/LinearAlgebra.jl/pull/1158 end @eval +(a::AbstractZeros, b::$TYPE) = b + a end @@ -480,11 +482,6 @@ end a .+ getindex_value(b) end -# following needed since as of Julia v1.8 convert(AbstractArray{T}, ::AbstractRange) might return a Vector -@inline elconvert(::Type{T}, A::AbstractRange) where T = T(first(A)):T(step(A)):T(last(A)) -@inline elconvert(::Type{T}, A::AbstractUnitRange) where T<:Integer = AbstractUnitRange{T}(A) -@inline elconvert(::Type{T}, A::AbstractArray) where T = AbstractArray{T}(A) - #### # norm ####