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

missing convert method #171

Closed
johnnychen94 opened this issue Dec 5, 2020 · 6 comments · Fixed by #230
Closed

missing convert method #171

johnnychen94 opened this issue Dec 5, 2020 · 6 comments · Fixed by #230

Comments

@johnnychen94
Copy link
Member

convert(Vector, 1:5)
convert(OffsetVector, 1:5) # doesn't work

Will it be type piracy if we define convert(::Type{T}, x) where {T<:OffsetArray}?

@chriselrod
Copy link
Collaborator

No, because OffsetArray is defined here. Although defining new convert methods tends to cause huge numbers of invalidations.

@chriselrod
Copy link
Collaborator

chriselrod commented Dec 5, 2020

What about something like

function Base.convert(::Type{T}, A::AbstractArray{<:Any,N}) where {N, T <: OffsetArray{<:Any,N}}
    OffsetArray(A, ntuple(zero, Val(N))...)
end

?

@jishnub
Copy link
Member

jishnub commented Dec 6, 2020

Related to this conversion is the constructor (::Type{<:OffsetArray})(::Array), which might resolve this issue with DistributedArrays.jl. The offending line appears to be
https://github.com/JuliaParallel/DistributedArrays.jl/blob/b98875d16c6810d33498405d5d852a3acee19b38/src/darray.jl#L66, where, given a type A, the function tries to construct an empty object of that type through

empty_localpart(T,N,A) = A(Array{T}(undef, ntuple(zero, N)))

I wonder if it's worth adding the constructor as well? Although if this conversion is added, it might be possible for DistributedArrays to use that instead of the constructor, as ultimately this operation is a conversion of an Array to an object of the type A

@jishnub
Copy link
Member

jishnub commented Dec 6, 2020

What about something like

function Base.convert(::Type{T}, A::AbstractArray{<:Any,N}) where {N, T <: OffsetArray{<:Any,N}}
    OffsetArray(A, ntuple(zero, Val(N))...)
end

?

We'll perhaps need to convert or constrain the eltype too to avoid cases like

julia> convert(OffsetArray{Float32,2}, rand(2,2))
2×2 OffsetArray(::Array{Float64,2}, 1:2, 1:2) with eltype Float64 with indices 1:2×1:2:
 0.580097  0.655686
 0.406192  0.0662347

Whether or not we allow the eltype to change is subject to how we view this conversion. If it is simply viewed as an identity map applied to the indices of the parent array then the element type should remain the same. On the other hand constraining the element type might make the conversion too narrow in scope, and it might be worth passing on the eltype conversion to the parent.

@GregPlowman
Copy link
Contributor

Not sure if this is the same issue, but I think I want a more narrow convert.

I would like to convert between OffsetArrays where the backing AbstractArray can be converted.

Base.convert(::Type{OffsetArray{T,N,A}}, x::OffsetArray{S,N}) where {T,N,A,S} = OffsetArray(convert(A, x.parent), x.offsets)

One scenario for this:

using OffsetArrays

struct Foo1
    a::Array{Float64,1}
end

struct Foo2
    o::OffsetArray{Float64,1,Array{Float64,1}}
end

A = zeros(Int, 3)
O = zeros(Int, 0:2)

Foo1(A)  # converts on construction
Foo2(O)  # errors without the extra convert method defined

@jishnub
Copy link
Member

jishnub commented Jan 23, 2021

Perhaps a combination of

julia> function Base.convert(::Type{OffsetArray{T,N,AA}}, A::AbstractArray{<:Any,N}) where {T, N, AA}
           OffsetArray{T,N,AA}(convert(AA, A), ntuple(zero, Val(N)))
       end
              
julia> function Base.convert(::Type{OffsetArray{T,N,AA}}, A::OffsetArray{<:Any,N}) where {T, N, AA}
           OffsetArray{T,N,AA}(convert(AA, A.parent), A.offsets)
       end

might help with conversions where all the type parameters are specified? With these, both the constructors work:

julia> Foo2(A)
Foo2([0.0, 0.0, 0.0])

julia> Foo2(O)
Foo2([0.0, 0.0, 0.0])

We might need other method for more general conversions such as in the top post. Not sure what's the best way to go about these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants