Skip to content

Commit

Permalink
Merge branch 'master' into dh/fix_views
Browse files Browse the repository at this point in the history
# Conflicts:
#	README.md
#	test/subviews.jl
  • Loading branch information
lindahua committed Jan 26, 2017
2 parents 7973a3a + 93e8039 commit 50707f2
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 14 deletions.
8 changes: 1 addition & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ os:
julia:
- 0.5
- nightly
before_install:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
script:
- julia -e 'versioninfo(); Pkg.init(); Pkg.clone(pwd());'
- if [ $TRAVIS_JULIA_VERSION = "nightly" ]; then julia -e 'Pkg.test("ArrayViews", coverage=true)'; fi
- if [ $TRAVIS_JULIA_VERSION = "release" ]; then julia -e 'Pkg.test("ArrayViews")'; fi
after_success:
- if [ $TRAVIS_JULIA_VERSION = "nightly" ]; then julia -e 'cd(Pkg.dir("ArrayViews")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'; fi
- julia -e 'cd(Pkg.dir("ArrayViews")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())';
notifications:
email: false
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,44 @@ A Julia package to explore a new system of array views.

-----------------------------

## For users of julia 0.4 or higher

By and large, this package is no longer necessary: base julia now has
efficient `SubArrays` (i.e., `sub` and `slice`). In choosing whether
to use `SubArray`s or the `ArrayView`s package, here are some
considerations:

Reasons to prefer `SubArrays`:

- `ArrayViews` can only make a view of an `Array`, whereas `SubArray`s
can create a view of any `AbstractArray`.

- The views created by `ArrayViews` are most efficient for
`ContiguousView`s such as column slices. In contrast, the views
created by `SubArray`s are efficient for any type of view (e.g.,
also row slices), in some cases resulting in a 3- to 10-fold
advantage. In either case, it's generally recommended to write functions
using cartesian indexing rather than linear indexing (e.g.,
`for I in eachindex(S)` rather than `for i = 1:length(S)`),
although in both cases there are some view types that are also
efficient under linear indexing.

- `SubArray`s allow more general slicing behavior, e.g., you can make
a view with `S = sub(A, [1,3,17], :)`.

- By default, `SubArray`s check bounds upon construction whereas
`ArrayView`s do not: `V = view(A, -5:10, :)` does not generate an
error, and if `V` is used in a function with an `@inbounds`
declaration you are likely to get a segfault. (You can bypass
bounds checking with `Base._sub` and `Base._slice`, in cases where
you want out-of-bounds construction for `SubArray`s.)

Reasons to prefer `ArrayViews`:

- Construction of `SubArray`s is frequently (but not always) 2-4 times
slower than construction of `view`s. If you are constructing many
column views, `ArrayView`s may still be the better choice.

## Main Features

- An efficient ``aview`` function that implements array views
Expand Down Expand Up @@ -141,8 +179,6 @@ v2 = unsafe_aview(v1, :, i) # of type UnsafeStridedView{Float64, 1, 0}
```

Four kinds of indexers are supported, integer, range (*e.g.* ``a:b``), stepped range (*e.g.* ``a:b:c``), and colon (*i.e.*, ``:``).
Unlike the ``sub`` function in Julia Base, the colon ``:`` is specially treated rather than converted to ``1:size(v,d)``, as it plays a crucial role in determining contiguousness. For example, the contiguous rank of ``aview(a, :, a:b)`` is 2, while that of ``aview(a, i:j, a:b)`` is 1.


## View Construction

Expand Down
30 changes: 28 additions & 2 deletions src/subviews.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,32 @@ roffset{T}(a::StridedArray{T,3}, i1::SubsNC, i2::SubsNC, i3::Colon) =
roffset{T}(a::StridedArray{T,3}, i1::SubsNC, i2::SubsNC, i3::SubsNC) =
_offset(i1) * stride(a,1) + _offset(i2) * stride(a,2) + _offset(i3) * stride(a,3)


# 4D (partial)
function roffset(a::ContiguousArray, i1::Subs, i2::Subs, i3::Subs, i4::Subs)
o = _offset(i1)
s = size(a,1)
o += s * _offset(i2)
o += (s *= size(a,2)) * _offset(i3)
o += (s *= size(a,3)) * _offset(i4)
return o
end

function roffset(a::ContiguousArray, i1::Colon, i2::Subs, i3::Subs, i4::Subs)
s = size(a,1)
o = s * _offset(i2)
o += (s *= size(a,2)) * _offset(i3)
o += (s *= size(a,3)) * _offset(i4)
return o
end

function roffset(a::ContiguousArray, i1::Colon, i2::Colon, i3::Subs, i4::Subs)
s = size(a,1)
o = (s *= size(a,2)) * _offset(i3)
o += (s *= size(a,3)) * _offset(i4)
return o
end

# General

roffset(a::ContiguousArray, i1::Colon, i2::Colon, i3::Colon, i4::Colon, I::Colon...) = 0
Expand All @@ -107,7 +133,7 @@ function roffset(a::ContiguousArray, i1::Subs, i2::Subs, i3::Subs, i4::Subs, I::
for i = 1:length(I)
o += (s *= size(a,i+3)) * _offset(I[i])
end
return o::Int
return o
end

roffset(a::StridedArray, i1::Subs, i2::Subs, i3::Subs, I::Subs...) =
Expand All @@ -118,7 +144,7 @@ function _roffset{N}(ss::NTuple{N,Int}, subs::NTuple{N})
for i = 2:N
o += _offset(subs[i]) * ss[i]
end
return o::Int
return o
end


Expand Down
30 changes: 27 additions & 3 deletions test/subviews.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ function _test_arrview(a, r, subs...)
end

macro test_arrview(a_, subs...)
esc(:(_test_arrview($a_, ($a_)[$(subs...)], $(subs...))))
esc(:(_test_arrview($a_, $a_[$(subs...)], $(subs...))))
end

#### test views from arrays

avparent = Array(reshape(1.:1680., (8, 7, 6, 5)))
avparent = copy(reshape(1.:1680., (8, 7, 6, 5)))

# 1D
println(" -- testing 1D views")
Expand Down Expand Up @@ -218,6 +218,30 @@ println(" -- testing 4D views")
@test_arrview(avparent, 1:2:7, :, 3:5, 2:5)
@test_arrview(avparent, 1:2:7, :, 1:2:5, 2:5)

@test_arrview(avparent, :, 1, 1, 1)
@test_arrview(avparent, :, 1, 2, 1)
@test_arrview(avparent, :, :, 2, 2)
@test_arrview(avparent, :, :, 1:2, 3:4)


# Some 5D tests
avparent2 = copy(reshape(1.:6720., (8, 7, 6, 5, 4)))

@test_arrview(avparent2, :, 1, 1, 1, 1)
@test_arrview(avparent2, :, 1, 1, 3, 1)
@test_arrview(avparent2, :, 1, 2, 3, 3:4)
@test_arrview(avparent2, 2:7, 1, 1, 1, 3:4)

@test_arrview(avparent2, 1, :, 1, 3, 4)
@test_arrview(avparent2, 2, 3, :, 3, 4)
@test_arrview(avparent2, 3, 4, 5, :, 4)
@test_arrview(avparent2, 2, 3, 4, 4, :)

@test_arrview(avparent2, 1, 2:3, 3, 4, 2)
@test_arrview(avparent2, 2, 1, 3:4, 1, 1)
@test_arrview(avparent2, 3, 1, 1, 4:5, 2)
@test_arrview(avparent2, 4, 1, 1, 3:4, 2:4)

#### Test Subviews of Views

function print_subscripts(subs1, subs2)
Expand All @@ -238,7 +262,7 @@ function test_arrview2(a, subs1, subs2)
_test_arrview_contents(unsafe_aview(uv, subs2...), v2r)
end

avparent = Array(reshape(1:6912, (12, 12, 8, 6)))
avparent = copy(reshape(1:6912, (12, 12, 8, 6)))

# 1D --> 1D
println(" -- testing 1D sub-views of 1D views")
Expand Down

0 comments on commit 50707f2

Please sign in to comment.