Skip to content

Commit 0513eed

Browse files
tpapptimholy
authored andcommitted
Add no_offset_view (#66)
1 parent b06de67 commit 0513eed

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

src/OffsetArrays.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,39 @@ printindices(io::IO, ind1) = print(io, _unslice(ind1))
200200
_unslice(x) = x
201201
_unslice(x::IdentityUnitRange) = x.indices
202202

203+
"""
204+
no_offset_view(A)
205+
206+
Return an `AbstractArray` that shares structure and has the same type and size as the
207+
argument, but has 1-based indexing. May just return the argument when applicable. Not
208+
exported.
209+
210+
The default implementation uses `OffsetArrays`, but other types should use something more
211+
specific to remove a level of indirection when applicable.
212+
213+
```jldoctest
214+
julia> O = OffsetArray(A, 0:1, -1:1)
215+
OffsetArray(::Array{Int64,2}, 0:1, -1:1) with eltype Int64 with indices 0:1×-1:1:
216+
1 3 5
217+
2 4 6
218+
219+
julia> OffsetArrays.no_offset_view(O)[1,1] = -9
220+
-9
221+
222+
julia> A
223+
2×3 Array{Int64,2}:
224+
-9 3 5
225+
2 4 6
226+
```
227+
"""
228+
function no_offset_view(A::AbstractArray)
229+
if Base.has_offset_axes(A)
230+
OffsetArray(A, map(r->1-first(r), axes(A)))
231+
else
232+
A
233+
end
234+
end
235+
236+
no_offset_view(A::OffsetArray) = no_offset_view(parent(A))
237+
203238
end # module

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CatIndices

test/runtests.jl

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
using OffsetArrays
22
using Test
33
using DelimitedFiles
4-
using OffsetArrays: IdentityUnitRange
4+
using OffsetArrays: IdentityUnitRange, no_offset_view
5+
using CatIndices: BidirectionalVector
56

67
@test isempty(detect_ambiguities(OffsetArrays, Base, Core))
78

@@ -402,6 +403,44 @@ end
402403
@test typeof(OffsetVector{Float64}(undef, -2:2)) == typeof(OffsetArray{Float64}(undef, -2:2))
403404
end
404405

406+
####
407+
#### type defined for testing no_offset_view
408+
####
409+
410+
struct NegativeArray{T,N,S <: AbstractArray{T,N}} <: AbstractArray{T,N}
411+
parent::S
412+
end
413+
414+
Base.axes(A::NegativeArray) = map(n -> (-n):(-1), size(A.parent))
415+
416+
Base.size(A::NegativeArray) = size(A.parent)
417+
418+
function Base.getindex(A::NegativeArray{T,N}, I::Vararg{Int,N}) where {T,N}
419+
getindex(A.parent, (I .+ size(A.parent) .+ 1)...)
420+
end
421+
422+
@testset "no offset view" begin
423+
# OffsetArray fallback
424+
A = randn(3, 3)
425+
O1 = OffsetArray(A, -1:1, 0:2)
426+
O2 = OffsetArray(O1, -2:0, -3:(-1))
427+
@test no_offset_view(O2) A
428+
429+
# generic fallback
430+
A = collect(reshape(1:12, 3, 4))
431+
N = NegativeArray(A)
432+
@test N[-3, -4] == 1
433+
V = no_offset_view(N)
434+
@test collect(V) == A
435+
436+
# bidirectional
437+
B = BidirectionalVector([1, 2, 3])
438+
pushfirst!(B, 0)
439+
OB = OffsetArrays.no_offset_view(B)
440+
@test axes(OB, 1) == 1:4
441+
@test collect(OB) == 0:3
442+
end
443+
405444
@testset "no nesting" begin
406445
A = randn(2, 3)
407446
x = A[2, 2]

0 commit comments

Comments
 (0)