|
1 | 1 | # This file is a part of Julia. License is MIT: http://julialang.org/license |
2 | 2 |
|
3 | | -# OffsetArrays (arrays with indexing that doesn't start at 1) |
4 | | - |
5 | | -# This test file is designed to exercise support for generic indexing, |
6 | | -# even though offset arrays aren't implemented in Base. |
7 | | - |
8 | | -module OAs |
9 | | - |
10 | | -using Base: Indices, LinearSlow, LinearFast, tail |
11 | | - |
12 | | -export OffsetArray |
13 | | - |
14 | | -immutable OffsetArray{T,N,AA<:AbstractArray} <: AbstractArray{T,N} |
15 | | - parent::AA |
16 | | - offsets::NTuple{N,Int} |
17 | | -end |
18 | | -typealias OffsetVector{T,AA<:AbstractArray} OffsetArray{T,1,AA} |
19 | | - |
20 | | -OffsetArray{T,N}(A::AbstractArray{T,N}, offsets::NTuple{N,Int}) = OffsetArray{T,N,typeof(A)}(A, offsets) |
21 | | -OffsetArray{T,N}(A::AbstractArray{T,N}, offsets::Vararg{Int,N}) = OffsetArray(A, offsets) |
22 | | - |
23 | | -(::Type{OffsetArray{T,N}}){T,N}(inds::Indices{N}) = OffsetArray{T,N,Array{T,N}}(Array{T,N}(map(length, inds)), map(indsoffset, inds)) |
24 | | -(::Type{OffsetArray{T}}){T,N}(inds::Indices{N}) = OffsetArray{T,N}(inds) |
25 | | - |
26 | | -Base.linearindexing{T<:OffsetArray}(::Type{T}) = Base.linearindexing(parenttype(T)) |
27 | | -parenttype{T,N,AA}(::Type{OffsetArray{T,N,AA}}) = AA |
28 | | -parenttype(A::OffsetArray) = parenttype(typeof(A)) |
29 | | - |
30 | | -Base.parent(A::OffsetArray) = A.parent |
31 | | - |
32 | | -errmsg(A) = error("size not supported for arrays with indices $(indices(A)); see http://docs.julialang.org/en/latest/devdocs/offset-arrays/") |
33 | | -Base.size(A::OffsetArray) = errmsg(A) |
34 | | -Base.size(A::OffsetArray, d) = errmsg(A) |
35 | | -Base.eachindex(::LinearSlow, A::OffsetArray) = CartesianRange(indices(A)) |
36 | | -Base.eachindex(::LinearFast, A::OffsetVector) = indices(A, 1) |
37 | | - |
38 | | -# Implementations of indices and indices1. Since bounds-checking is |
39 | | -# performance-critical and relies on indices, these are usually worth |
40 | | -# optimizing thoroughly. |
41 | | -@inline Base.indices(A::OffsetArray, d) = 1 <= d <= length(A.offsets) ? indices(parent(A))[d] + A.offsets[d] : (1:1) |
42 | | -@inline Base.indices(A::OffsetArray) = _indices(indices(parent(A)), A.offsets) # would rather use ntuple, but see #15276 |
43 | | -@inline _indices(inds, offsets) = (inds[1]+offsets[1], _indices(tail(inds), tail(offsets))...) |
44 | | -_indices(::Tuple{}, ::Tuple{}) = () |
45 | | -Base.indices1{T}(A::OffsetArray{T,0}) = 1:1 # we only need to specialize this one |
46 | | - |
47 | | -function Base.similar(A::OffsetArray, T::Type, dims::Dims) |
48 | | - B = similar(parent(A), T, dims) |
49 | | -end |
50 | | -function Base.similar(A::AbstractArray, T::Type, inds::Tuple{UnitRange,Vararg{UnitRange}}) |
51 | | - B = similar(A, T, map(length, inds)) |
52 | | - OffsetArray(B, map(indsoffset, inds)) |
53 | | -end |
54 | | - |
55 | | -Base.similar(f::Union{Function,DataType}, shape::Tuple{UnitRange,Vararg{UnitRange}}) = OffsetArray(f(map(length, shape)), map(indsoffset, shape)) |
56 | | - |
57 | | -Base.reshape(A::AbstractArray, inds::Tuple{UnitRange,Vararg{UnitRange}}) = OffsetArray(reshape(A, map(length, inds)), map(indsoffset, inds)) |
58 | | - |
59 | | -@inline function Base.getindex{T,N}(A::OffsetArray{T,N}, I::Vararg{Int,N}) |
60 | | - checkbounds(A, I...) |
61 | | - @inbounds ret = parent(A)[offset(A.offsets, I)...] |
62 | | - ret |
63 | | -end |
64 | | -@inline function Base._getindex(::LinearFast, A::OffsetVector, i::Int) |
65 | | - checkbounds(A, i) |
66 | | - @inbounds ret = parent(A)[offset(A.offsets, (i,))[1]] |
67 | | - ret |
68 | | -end |
69 | | -@inline function Base._getindex(::LinearFast, A::OffsetArray, i::Int) |
70 | | - checkbounds(A, i) |
71 | | - @inbounds ret = parent(A)[i] |
72 | | - ret |
73 | | -end |
74 | | -@inline function Base.setindex!{T,N}(A::OffsetArray{T,N}, val, I::Vararg{Int,N}) |
75 | | - checkbounds(A, I...) |
76 | | - @inbounds parent(A)[offset(A.offsets, I)...] = val |
77 | | - val |
78 | | -end |
79 | | -@inline function Base._setindex!(::LinearFast, A::OffsetVector, val, i::Int) |
80 | | - checkbounds(A, i) |
81 | | - @inbounds parent(A)[offset(A.offsets, (i,))[1]] = val |
82 | | - val |
83 | | -end |
84 | | -@inline function Base._setindex!(::LinearFast, A::OffsetArray, val, i::Int) |
85 | | - checkbounds(A, i) |
86 | | - @inbounds parent(A)[i] = val |
87 | | - val |
88 | | -end |
89 | | - |
90 | | -# Computing a shifted index (subtracting the offset) |
91 | | -offset{N}(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) = _offset((), offsets, inds) |
92 | | -_offset(out, ::Tuple{}, ::Tuple{}) = out |
93 | | -@inline _offset(out, offsets, inds) = _offset((out..., inds[1]-offsets[1]), Base.tail(offsets), Base.tail(inds)) |
94 | | - |
95 | | -indsoffset(r::Range) = first(r) - 1 |
96 | | -indsoffset(i::Integer) = 0 |
97 | | - |
98 | | -end |
99 | | - |
100 | | -using OAs |
| 3 | +isdefined(:TestHelpers) || include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) |
| 4 | +using TestHelpers.OAs |
101 | 5 |
|
102 | 6 | let |
103 | 7 | # Basics |
@@ -219,11 +123,11 @@ cmp_showf(Base.print_matrix, io, OffsetArray(rand(5,5), (10,-9))) # rows&c |
219 | 123 | cmp_showf(Base.print_matrix, io, OffsetArray(rand(10^3,5), (10,-9))) # columns fit |
220 | 124 | cmp_showf(Base.print_matrix, io, OffsetArray(rand(5,10^3), (10,-9))) # rows fit |
221 | 125 | cmp_showf(Base.print_matrix, io, OffsetArray(rand(10^3,10^3), (10,-9))) # neither fits |
222 | | -targets1 = ["0-dimensional OAs.OffsetArray{Float64,0,Array{Float64,0}}:\n1.0", |
223 | | - "OAs.OffsetArray{Float64,1,Array{Float64,1}} with indices 2:2:\n 1.0", |
224 | | - "OAs.OffsetArray{Float64,2,Array{Float64,2}} with indices 2:2×3:3:\n 1.0", |
225 | | - "OAs.OffsetArray{Float64,3,Array{Float64,3}} with indices 2:2×3:3×4:4:\n[:, :, 4] =\n 1.0", |
226 | | - "OAs.OffsetArray{Float64,4,Array{Float64,4}} with indices 2:2×3:3×4:4×5:5:\n[:, :, 4, 5] =\n 1.0"] |
| 126 | +targets1 = ["0-dimensional TestHelpers.OAs.OffsetArray{Float64,0,Array{Float64,0}}:\n1.0", |
| 127 | + "TestHelpers.OAs.OffsetArray{Float64,1,Array{Float64,1}} with indices 2:2:\n 1.0", |
| 128 | + "TestHelpers.OAs.OffsetArray{Float64,2,Array{Float64,2}} with indices 2:2×3:3:\n 1.0", |
| 129 | + "TestHelpers.OAs.OffsetArray{Float64,3,Array{Float64,3}} with indices 2:2×3:3×4:4:\n[:, :, 4] =\n 1.0", |
| 130 | + "TestHelpers.OAs.OffsetArray{Float64,4,Array{Float64,4}} with indices 2:2×3:3×4:4×5:5:\n[:, :, 4, 5] =\n 1.0"] |
227 | 131 | targets2 = ["(1.0,1.0)", |
228 | 132 | "([1.0],[1.0])", |
229 | 133 | "(\n[1.0],\n\n[1.0])", |
|
0 commit comments