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

RFC: use offset axes for offset arrays #27038

Merged
merged 11 commits into from
May 29, 2018

Conversation

mbauman
Copy link
Member

@mbauman mbauman commented May 9, 2018

This is a shot at solving some of the difficulties we faced in #26682 (comment) by ensuring the axes of an offset array are similarly offset such that ax[i] == i for each ax in axes(A). This is an idea that's been bouncing around for a while — I believe Andy Ferris first posited it. It does seem to solve some of the issues we faced, but I'm still not quite to the end of this tunnel.

The goal here is to fully support LinearIndices and CartesianIndices as generic replacements for ind2sub and sub2ind for both normal and offset arrays. The issue with the design in #26682 (which achieves this goal) is that it makes CartesianIndices((20:30, 20:30)) an offset array itself! This was a breaking change for folks that took full advantage of the CartesianIndices object. This PR, instead, is experimenting with making these indices-wrapper types reflect the axes of their indices and making OffsetArrays have offset axes. The goal is to enable the following properties for both normal and offset arrays A:

A == A[axes(A)...] == A[LinearIndices(A)] == A[CartesianIndices(A)]
LinearIndices(A) == LinearIndices(A)[axes(A)...] == LinearIndices(A)[LinearIndices(A)] == LinearIndices(A)[CartesianIndices(A)]
CartesianIndices(A) == CartesianIndices(A)[axes(A)...] == CartesianIndices(A)[LinearIndices(A)] == CartesianIndices(A)[CartesianIndices(A)]

One thing that could use some bikeshedding is the name and use of Base.Slice — do we export it? It's now pulling double-duty: OffsetArrays use it both as their axis type and as a flag to SubArray that a given index represents an entire dimension. It might be interesting to try experimenting with returning Slice{OneTo}s as the axes to normal arrays, too. For example, view(A, axes(A)...) isn't ever IndexLinear, even if view(A, :, :, …) would be.

@mbauman mbauman added arrays [a, r, r, a, y, s] triage This should be discussed on a triage call labels May 9, 2018
base/array.jl Outdated
@@ -545,7 +545,7 @@ else
end

_array_for(::Type{T}, itr, ::HasLength) where {T} = Vector{T}(undef, Int(length(itr)::Integer))
_array_for(::Type{T}, itr, ::HasShape) where {T} = similar(Array{T}, axes(itr))::Array{T}
_array_for(::Type{T}, itr, ::HasShape) where {T} = similar(Array{T}, axes(itr))
Copy link
Member Author

Choose a reason for hiding this comment

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

This was required due to the change in sort.jl to a comprehension, which in turn was required because we were using the existence of a Slice to determine where a : was placed. There could be another workaround for that if this is deemed undesirable… but it seems quite nice to be able to create similarly offset arrays simply with [B[i,j] for (i,j) in axes(A)].

Copy link
Member

Choose a reason for hiding this comment

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

This moves in the opposite direction of what I'm doing in #25861 (narrowing the type-assertion). However, if we have to pick one the two, I guess this one should have priority.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do we get the same benefit from ::AbstractArray{T,N}?

Copy link
Member Author

Choose a reason for hiding this comment

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

Also note that this change isn't completely predicated by the change in axis representation.

While it's not been tested, the introduction of this assertion broke things like [x for x in A] if A is an offset array. That had worked on 0.6.

Copy link
Member

Choose a reason for hiding this comment

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

Looks like with the explicit introduction of N, we need no type assertion at all 🎉 I've removed it from #25861, too.

@mbauman mbauman added the breaking This change will break code label May 9, 2018
mbauman added a commit to mbauman/OffsetArrays.jl that referenced this pull request May 10, 2018
@mbauman mbauman changed the title WIP: use offset axes for offset arrays RFC: use offset axes for offset arrays May 10, 2018
@mbauman
Copy link
Member Author

mbauman commented May 10, 2018

@timholy I'd love to hear your input here.

@Keno Keno removed the triage This should be discussed on a triage call label May 10, 2018
@martinholters
Copy link
Member

Should we milestone this?

@StefanKarpinski
Copy link
Member

Or put another way, I'm not sure why the triage label was removed without comment. It's generally best to at least leave a comment as to why something is being de-triaged.

@StefanKarpinski StefanKarpinski added the triage This should be discussed on a triage call label May 14, 2018
@mbauman
Copy link
Member Author

mbauman commented May 14, 2018

The consensus from triage was that it hadn't been open too long and it'd be nice to hear more feedback before making a final decision. Re-triaging this week makes sense.

@andyferris
Copy link
Member

I haven't had a chance to delve into the details - but I love the stated properties and support the outcome. (BTW I think it was Tim that first pointed out to me that this property was desirable for Slice, but I can't dig up where).

@Keno
Copy link
Member

Keno commented May 17, 2018

Or put another way, I'm not sure why the triage label was removed without comment. It's generally best to at least leave a comment as to why something is being de-triaged.

Triage decision was to ask @timholy to review ;).

@maleadt
Copy link
Member

maleadt commented May 18, 2018

@mbauman ... did you really intent to include a fax machine in your branch name? because that broke the JuliaGPU buildbot (the GitPoller to be specific, when ASCII encoding cmdline args to git fetch)
EDIT: easy enough fix over at the buildbot side, so don't worry about it 🙂

@mbauman
Copy link
Member Author

mbauman commented May 18, 2018

Whoops, I'm sorry my bad pun caused extra work for you!

@StefanKarpinski
Copy link
Member

StefanKarpinski commented May 24, 2018

Triage supports trying this out in 0.7-alpha and reverting before 1.0 if it's a disaster. Seems like it may be a big win but it's essentially impossible to know without trying.

@martinholters
Copy link
Member

Is there anything here that needs to be done before merging?

@ViralBShah
Copy link
Member

I have restarted Appveyor.

@JeffBezanson JeffBezanson added this to the 0.7 milestone May 28, 2018
@JeffBezanson JeffBezanson removed the triage This should be discussed on a triage call label May 28, 2018
@JeffBezanson JeffBezanson merged commit 8e6cfff into master May 29, 2018
@JeffBezanson JeffBezanson deleted the mb/axesofindicesofaxesofindiceso📠s branch May 29, 2018 03:37
@fredrikekre
Copy link
Member

This changed the output back to what it was some weeks ago (https://github.com/JuliaLang/julia/pull/27000/files#diff-89e97f67f8058d32eac8d917db5bbdbf) so broke some doctests

diff --git a/base/indices.jl b/base/indices.jl
index a05a7c0..06690a1 100644
--- a/base/indices.jl
+++ b/base/indices.jl
@@ -336,7 +336,7 @@ from cartesian to linear indexing:
 
 ```jldoctest
 julia> linear = LinearIndices((1:3, 1:2))
-LinearIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}} with indices 1:3×1:2:
+3×2 LinearIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}}:
  1  4
  2  5
  3  6
diff --git a/base/multidimensional.jl b/base/multidimensional.jl
index 4c390f7..78b3d4f 100644
--- a/base/multidimensional.jl
+++ b/base/multidimensional.jl
@@ -202,7 +202,7 @@ module IteratorsMD
 
     ```jldoctest
     julia> cartesian = CartesianIndices((1:3, 1:2))
-    CartesianIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}} with indices 1:3×1:2:
+    3×2 CartesianIndices{2,Tuple{UnitRange{Int64},UnitRange{Int64}}}:
      CartesianIndex(1, 1)  CartesianIndex(1, 2)
      CartesianIndex(2, 1)  CartesianIndex(2, 2)
      CartesianIndex(3, 1)  CartesianIndex(3, 2)

@KristofferC
Copy link
Member

CI ran 2 weeks ago here and when it has been that long, it is good to restart it imo.

@JeffBezanson
Copy link
Member

Are there no tests for the changed printing? We should add some.

@mbauman
Copy link
Member Author

mbauman commented May 29, 2018

Sure, I'll add a few more tests here. Looks like this will be fixed in #27294.

mbauman pushed a commit that referenced this pull request May 29, 2018
* Some more examples/refs for array docs

* fix doctests from #27038 (comment)
mbauman added a commit to mbauman/OffsetArrays.jl that referenced this pull request Jun 6, 2018
mbauman added a commit to JuliaArrays/OffsetArrays.jl that referenced this pull request Jun 26, 2018
* Make OffsetArray's axes offset themselves

This is the companion PR to JuliaLang/julia#27038.

* Display slices as simple ranges in show -- we allow constructing OffsetArrays in this manner

* Add compatibility for 0.6
@timholy
Copy link
Member

timholy commented Jul 2, 2018

Sorry about being unresponsive when this was posted. This fixes some of the bugs I addressed in #21052, so I'll close that.

Long term, it's unfortunate that Slice does double-duty. https://github.com/JuliaArrays/IdentityRanges.jl splits the two concepts; if we wanted to, we could introduce an IdentityRange (also considered as a name was IdempotentRange, because r[r] === r) and then use Slice as a trivial wrapper that signals "whole dimension."

@andyferris
Copy link
Member

andyferris commented Jul 2, 2018

+1, Tim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arrays [a, r, r, a, y, s] breaking This change will break code
Projects
None yet
Development

Successfully merging this pull request may close these issues.