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

properly handle colon in offset reshape #228

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

johnnychen94
Copy link
Member

@johnnychen94 johnnychen94 commented Apr 11, 2021

As a placeholder for a slice, Colon at the k-th position also preserves the offset of the axes(A, k). The default offset for k>=ndims(A) is assumed to be 0.

The implementation is based on https://github.com/JuliaLang/julia/blob/d29126a43ee289fc5ab8fcb3dc0e03f514605950/base/reshapedarray.jl#L119-L137

closes #220

cc: @jishnub

@codecov
Copy link

codecov bot commented Apr 11, 2021

Codecov Report

Merging #228 (bf24c31) into master (b74ae55) will decrease coverage by 0.14%.
The diff coverage is 96.55%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #228      +/-   ##
==========================================
- Coverage   94.40%   94.26%   -0.15%     
==========================================
  Files           5        5              
  Lines         322      349      +27     
==========================================
+ Hits          304      329      +25     
- Misses         18       20       +2     
Impacted Files Coverage Δ
src/utils.jl 96.15% <96.00%> (-3.85%) ⬇️
src/OffsetArrays.jl 98.17% <100.00%> (+0.01%) ⬆️

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 b74ae55...bf24c31. Read the comment docs.

include("axes.jl")
include("utils.jl")
include("origin.jl")

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 is to let utils.jl know the OffsetAxisKnownLength and OffsetAxis.

For better compatibility to old and future Julia versions
@jishnub
Copy link
Member

jishnub commented Apr 11, 2021

Since this changes the axes of the reshaped array, this should perhaps be treated as a breaking change?

@johnnychen94
Copy link
Member Author

johnnychen94 commented Apr 11, 2021

Since we never successfully supported Colon in reshape before (had we?), I would say this is just a new feature. A minor version should be sufficient.

@jishnub
Copy link
Member

jishnub commented Apr 11, 2021

This works currently on master:

julia> A = zeros(1:2, 3:4)
2×2 OffsetArray(::Matrix{Float64}, 1:2, 3:4) with eltype Float64 with indices 1:2×3:4:
 0.0  0.0
 0.0  0.0

julia> reshape(A, 2:3, :)
2×2 OffsetArray(::Matrix{Float64}, 2:3, 1:2) with eltype Float64 with indices 2:3×1:2:
 0.0  0.0
 0.0  0.0

After this PR:

julia> reshape(A, 2:3, :)
2×2 OffsetArray(::Matrix{Float64}, 2:3, 3:4) with eltype Float64 with indices 2:3×3:4:
 0.0  0.0
 0.0  0.0

@@ -280,13 +280,15 @@ end
Base.reshape(A::AbstractArray, inds::OffsetAxis...) = reshape(A, inds)
function Base.reshape(A::AbstractArray, inds::Tuple{OffsetAxis,Vararg{OffsetAxis}})
AR = reshape(A, map(_indexlength, inds))
return OffsetArray(AR, map(_offset, axes(AR), inds))
return OffsetArray(AR, _offset_reshape_uncolon(A, inds))
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 is equivalent to

    return OffsetArray(AR, map(_offset, axes(AR), _offset_reshape_uncolon(A, inds)))

By removing the map part, it calls another constructor.

# convert ranges to offsets
@eval @inline function $FT(A::AbstractArray, inds::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}})
_checkindices(A, inds, "indices")
# Performance gain by wrapping the error in a function: see https://github.com/JuliaLang/julia/issues/37558
throw_dimerr(lA, lI) = throw(DimensionMismatch("supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices"))
lA = size(A)
lI = map(length, inds)
lA == lI || throw_dimerr(lA, lI)
$FT(A, map(_offset, axes(A), inds))
end

@johnnychen94
Copy link
Member Author

Ahhhh... Didn't realize that it worked before. I think we need triage here on which solution we should take: #220 or this. @mbauman @timholy

@johnnychen94 johnnychen94 requested review from timholy and mbauman April 11, 2021 12:50
@jishnub
Copy link
Member

jishnub commented Apr 11, 2021

Perhaps some of the other methods need to be altered too to get this to be consistent:

julia> reshape(OffsetArray(3:4, 2), :) # preserves offset
3:4 with indices 3:4

julia> reshape(OffsetArray(3:4, 2), :, 1) # does not preserve offset
2×1 reshape(::UnitRange{Int64}, 2, 1) with eltype Int64:
 3
 4

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