FixedSizeArrays.jl
FixedSizeArrays.jl copied to clipboard
Strange loss of Type Specificity
using FixedSizeArrays
X = [rand(Vec{3,Float64}) for n = 1:10]
Xscal = X * 1.234
Xsub = view(X, 3:7)
Xsubscal = Xsub * 1.234
@show typeof(X)
@show typeof(Xscal)
@show typeof(Xsub)
@show typeof(Xsubscal)
Output:
typeof(X) = Array{FixedSizeArrays.Vec{3,Float64},1}
typeof(Xscal) = Array{FixedSizeArrays.Vec{3,Float64},1}
typeof(Xsub) = SubArray{FixedSizeArrays.Vec{3,Float64},1,Array{FixedSizeArrays.Vec{3,Float64},1},Tuple{UnitRange{Int64}},true}
typeof(Xsubscal) = Array{Any,1}
I had a bit of a dig. This goes via promote_array_type, which in turn ends up calling Base.promote_op(.*, Vec{3,Float64}, Float64) which comes out as Any.
In this specific case, a fix can be had in 0.5 by defining
Base.promote_op{F<:FixedArray,T<:Number}(::typeof(.*), ::Type{F}, ::Type{T}) = similar_type(F, promote_type(eltype(F), T))
More generally, the following would probably mostly work:
julia> using FixedSizeArrays
julia> Base.promote_op{Op,F<:FixedArray,T<:Number}(op::Op, ::Type{F}, ::Type{T}) = similar_type(F, Base.promote_op(op, eltype(F), T))
julia> Base.promote_op{Op,F<:FixedArray,T<:Number}(op::Op, ::Type{T}, ::Type{F}) = similar_type(F, Base.promote_op(op, T, eltype(F)))
julia> 1.0*view(Vec{3,Float64}[], 1:0)
0-element Array{FixedSizeArrays.Vec{3,Float64},1}
julia> view(Vec{3,Float64}[], 1:0)*1.0
0-element Array{FixedSizeArrays.Vec{3,Float64},1}
I think the machinery in Base is somewhat different here in 0.5 vs 0.4.
Yeah I keep adding definitions like that to fix the various corner cases :D
Might you be able to get rid of the promote_array_type overloads if you define the promote_op as above?