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

Generalized indices and arbitrary indexing support. #1

Merged
merged 5 commits into from
Dec 29, 2019

Conversation

yha
Copy link
Contributor

@yha yha commented Dec 24, 2019

Adds support for generalized (non-1-based) axes of the underlying array, as well as generalized indexing (e.g. by ranges or logical arrays).

Copy link
Owner

@Vexatos Vexatos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the pull request! Making this type more generally useful is very much appreciated. Support for OffsetArrays does sound useful.

# Ambiguity resolution with Base
@inline Base.similar(arr::CircularArray, ::Type{T}, dims::Tuple{Int64,Vararg{Int64}}) where T = _similar(arr,T,dims)
# Ambiguity resolution with OffsetArrays, for the case similar(arr) where arr.data::OffsetArray
@inline Base.similar(arr::CircularArray, ::Type{T}, dims::Tuple{OffsetAxis, Vararg{OffsetAxis}}) where T = _similar(arr,T,dims)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the hard dependency on OffsetArrays for this really necessary? I doubt that it would have to be. Why would this ambiguity resolution be needed at all? I'd like to avoid this hard dependency if possible, it's fine using the package for testing though.

Copy link
Contributor Author

@yha yha Dec 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason ambiguity resolution is needed is the similar method mentioned here: JuliaArrays/OffsetArrays.jl#87.
Without changes to Base or OffsetArrays, the only solutions I can see are:

  • a dependency on OffsetArrays
  • copy-pasting the OffsetAxis definition from OffsetArrays
  • defining our own axis type as suggested here Type-piracy in similar with OffsetAxis JuliaArrays/OffsetArrays.jl#87 (comment), and defining similar just for those. This would mean axes converts the underlying arrays axes to a custom range type, and similar does the opposite conversion to send the axes to the underlying array. This would solve the case similar(a::CircularArray) where a.data is offset, but not a direct call from user code like similar(a::CircularArray, -2:2, -2:2) (which would dispatch on the OffsetArrays definition and thus fail to produce a circular array). Perhaps I'm misunderstanding how this mechanism should be used. Maybe @timholy can elucidate? EDIT: actually, I tried this now and a lot of tests fail because indexing operations invoke similar with the index's axes, which sinks this whole approach.

Otherwise, I think changing Base and OffsetArrays as suggested here JuliaArrays/OffsetArrays.jl#87 (comment) would solve this problem too.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like an issue that needs to be fixed in OffsetArrays. I am not a fan of adding workarounds for problems in other packages in here.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's absolutely necessary, I'd rather copy the OffsetAxis definition over. It's just a tuple, after all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JuliaArrays/OffsetArrays.jl#90 shows an example of defining your own axis type. You can specialize axes for the axes, as done in that PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something, but as far as I can see, this OffsetArrays example works because it defines similar not only for its custom index types, but also for "standard" types appearing in the OffsetAxis union, because getindex(A,I...) generally calls similar with I's axes. We similarly can't avoid defining similar on the "standard" types, and then we're back with the ambiguity errors. If I only define similar for a custom axis type, then indexing ::CircularArray[::UnitRange] fails to produce a CircularArray (because it calls a similar method from base).
At this point, I don't see how a custom index type is helpful at all. For now I will resolve the ambiguity as in BlockArrays.jl.

test/runtests.jl Outdated Show resolved Hide resolved
test/runtests.jl Outdated Show resolved Hide resolved
@Vexatos Vexatos added the enhancement New feature or request label Dec 25, 2019
Copy link
Owner

@Vexatos Vexatos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd merge this without the hard dependency on OffsetArrays. I prefer the solution of copying over the trivial OffsetAxis definition, just like what BlockArrays.jl does. The backwards compatibility with julia ≤1.2 is something I may remove later myself.

@yha
Copy link
Contributor Author

yha commented Dec 28, 2019

I have replaced the OffsetArrays dependency with a copy of the OffsetAxis definition.

Copy link
Owner

@Vexatos Vexatos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't like having to resolve the ambiguity with OffsetArrays here, but the code looks good now. Thanks once again for this.

@Vexatos Vexatos merged commit 14392b9 into Vexatos:master Dec 29, 2019
@inline Base.checkbounds(::CircularArray, _...) = nothing

@inline _similar(arr::CircularArray, ::Type{T}, dims) where T = CircularArray(similar(arr.data,T,dims))
@inline Base.similar(arr::CircularArray, ::Type{T}, dims::Tuple{Base.DimOrInd, Vararg{Base.DimOrInd}}) where T = _similar(arr,T,dims)
Copy link
Owner

@Vexatos Vexatos Dec 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some more testing, I noticed that this line does not seem to be covered by the tests. Do you happen to have an example for where it might be used? Or did the addition of the ambiguity resolution for OffsetArrays cover this? Technically, this method is more broad than the one below since DimOrInd is more generic, but I cannot think of anything that would ever use this, short of someone implementing their own axis type, which would once again trigger the same ambiguity as below anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I added this before the ambiguity resolution.
I think you're right, and we will face an ambiguity error on similar when indexing with arrays defining a custom axis type in the "standard" way defined in the Julia docs. I tested this with CatIndices.BidirectionalVector, and indeed indexing c[bidi_vec] where c is a CircularArray triggers the ambiguity. If this more general similar method is removed the ambiguity disappears, but the result of indexing is no longer circular, which is inconsistent with c[a::Array].
I think maintaining the circularity in, e.g. c[1:5] is really useful, and it's unfortunate if we can't have it for c[i] where i has custom axes, but I'm not sure how it would be possible with how array indexing is designed in Base.

Copy link
Owner

@Vexatos Vexatos Jan 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I will keep this as it is for now. Thank you again for the contribution.

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

Successfully merging this pull request may close these issues.

3 participants