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

Use to_indices in the OffsetArray constructor #157

Merged
merged 5 commits into from
Sep 27, 2020

Conversation

jishnub
Copy link
Member

@jishnub jishnub commented Sep 21, 2020

This PR relaxes the types that may be passed to the constructor. After this, any type that may be converted to an AbstractUnitRange may be passed, including types defined in an external package.

For example, using EllipsisNotation.jl,

julia> OffsetArray(zeros(2,2,1), .., 3:3)
2×2×1 OffsetArray(::Array{Float64,3}, 1:2, 1:2, 3:3) with eltype Float64 with indices 1:2×1:2×3:3:
[:, :, 3] =
 0.0  0.0
 0.0  0.0

the leading axes are replaced by colons, and only the last index is offset.

The PR also fixes some indexing issues with IdOffsetRanges. Now indexing with offset rages are also idempotent.

julia> r = OffsetArrays.IdOffsetRange(3:5, -1)
OffsetArrays.IdOffsetRange(2:4)

julia> s = OffsetArrays.IdOffsetRange(-3:-2, 4)
OffsetArrays.IdOffsetRange(1:2)

julia> axes(r)
(OffsetArrays.IdOffsetRange(0:2),)

julia> r[s]
OffsetArrays.IdOffsetRange(3:4)

julia> axes(r[s]) == axes(s)
true

Also define Base.firstindex for an IdOfffsetRange to make it marginally faster wrt. master, now it's as fast as the parent.

julia> @btime firstindex($(Ref(r))[].parent)
  2.670 ns (0 allocations: 0 bytes)
1

julia> @btime firstindex($(Ref(r))[])
  2.670 ns (0 allocations: 0 bytes)
0

vs

# on master
julia> @btime firstindex($(Ref(r))[].parent)
  2.670 ns (0 allocations: 0 bytes)
1

julia> @btime firstindex($(Ref(r))[])
  3.196 ns (0 allocations: 0 bytes)
0

@codecov
Copy link

codecov bot commented Sep 21, 2020

Codecov Report

Merging #157 into master will increase coverage by 5.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #157      +/-   ##
==========================================
+ Coverage   94.60%   99.60%   +5.00%     
==========================================
  Files           4        4              
  Lines         241      256      +15     
==========================================
+ Hits          228      255      +27     
+ Misses         13        1      -12     
Impacted Files Coverage Δ
src/OffsetArrays.jl 99.44% <100.00%> (+4.01%) ⬆️
src/axes.jl 100.00% <100.00%> (+9.09%) ⬆️
src/utils.jl 100.00% <100.00%> (+6.25%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2ed1598...e3f8fd9. Read the comment docs.

@johnnychen94
Copy link
Member

johnnychen94 commented Sep 21, 2020

Haven't taken a look at the details but it looks nice. Should I get #148 in first, or get this in first?

Either way it requires some extra rebasing work to solve the conflicts.

@jishnub
Copy link
Member Author

jishnub commented Sep 21, 2020

Maybe #148 can go first as it is less of a change, more of a cleanup

@jishnub
Copy link
Member Author

jishnub commented Sep 24, 2020

I think it's worth splitting this PR into two, with the bugfixes and performance improvements going into the 1.2 series and the added feature into 1.3

@johnnychen94
Copy link
Member

johnnychen94 commented Sep 24, 2020 via email

@jishnub
Copy link
Member Author

jishnub commented Sep 24, 2020

As per semver, bugfixes should go in patch releases and features should go in minor releases. Origin and using to_indices therefore belong to 1.3. However bugfixes should go in 1.2.x.

Maybe once Origin is merged I can rebase on top of that if we target 1.3, otherwise it's for 1.4.

@johnnychen94
Copy link
Member

As per semver, bugfixes should go in patch releases and features should go in minor releases.

Strictly speaking, yes. I see the constructor rework and the origin feature as new features, so I'm targeting 1.3.0 and no more 1.2.x release. That said, I think it is totally fine to squash some bug fixes into a minor release; this frees us from managing different release branches with cherry-picks and back-ports or so...

Maybe once Origin is merged I can rebase on top of that if we target 1.3, otherwise it's for 1.4.

LOL #147 is already merged.

@jishnub jishnub force-pushed the to_indices branch 3 times, most recently from de948d1 to 9f26eb1 Compare September 25, 2020 21:18
@jishnub
Copy link
Member Author

jishnub commented Sep 25, 2020

This PR also modifies this behavior on master:

# on master
julia> OffsetVector(zeros(2,2), 1:2, 1:2)
2×2 OffsetArray(::Array{Float64,2}, 1:2, 1:2) with eltype Float64 with indices 1:2×1:2:
 0.0  0.0
 0.0  0.0
# this PR
julia> OffsetVector(zeros(2,2), 1:2, 1:2)
ERROR: ArgumentError: OffsetVector requires a 1D array

Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

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

Except for the additional dispatch complexity and the tendency to somehow revert #148 🤣 , it looks really nice!

src/OffsetArrays.jl Outdated Show resolved Hide resolved
src/utils.jl Outdated Show resolved Hide resolved
src/OffsetArrays.jl Outdated Show resolved Hide resolved
src/OffsetArrays.jl Show resolved Hide resolved
src/utils.jl Show resolved Hide resolved
src/OffsetArrays.jl Show resolved Hide resolved
docs/src/internals.md Outdated Show resolved Hide resolved
docs/src/internals.md Outdated Show resolved Hide resolved
to_indices converts colons to ranges. This is followed by converting CartesianIndices to ranges.
Fix indexing IdOffsetRange using offset ranges, ensuring that indexing is idempotent
Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

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

Thanks for doing this, really nice an improvement to make this generic! The test looks really awesome, too.

src/utils.jl Outdated Show resolved Hide resolved
src/OffsetArrays.jl Show resolved Hide resolved
# In general, indices get converted to AbstractUnitRanges.
# CartesianIndices{N} get converted to N ranges
@eval function $FT(A::AbstractArray, inds::Tuple)
@eval function $FT(A::AbstractArray, inds::Tuple{Any,Vararg{Any}})
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 isn't really necessary given the dispatch priority of Tuple{Vararg{Integer}} over Tuple, but helps to clarify that this method doesn't handle empty tuples.

# Nested OffsetArrays may strip off the wrapper and collate the offsets
@eval function $FT(A::OffsetArray, offsets::Tuple{Vararg{Integer}})
_checkindices(A, offsets, "offsets")
$FT(parent(A), map(+, A.offsets, offsets))
Copy link
Member Author

@jishnub jishnub Sep 27, 2020

Choose a reason for hiding this comment

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

Broadcasting treats values in Tuples as scalars as opposed to treating the Tuple as a collection in itself, so something like (1,2) .+ (1,) evaluates to (2,3). map, on the other hand, operates elementwise. This is not strictly necessary as _checkindices catches it anyway, but might help against future bugs.

@johnnychen94
Copy link
Member

johnnychen94 commented Sep 27, 2020

@jishnub you're doing really great work! Feel free to merge when you think it is ready.

I think this is the last piece we need to v1.3.0?

@jishnub
Copy link
Member Author

jishnub commented Sep 27, 2020

Maybe we can include #152 in 1.3 as well, now that julia 1.5.2 has been released

@jishnub jishnub merged commit b6a4f49 into JuliaArrays:master Sep 27, 2020
@jishnub jishnub deleted the to_indices branch January 17, 2021 08:57
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 this pull request may close these issues.

2 participants