Skip to content

Commit

Permalink
Merge pull request #47 from JuliaArrays/dh/fix_views
Browse files Browse the repository at this point in the history
Various fixes to make the package work with v0.5
  • Loading branch information
lindahua authored Feb 1, 2017
2 parents 93e8039 + 4f6a2ac commit 2ed35eb
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 172 deletions.
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ os:
- linux
- osx
julia:
- 0.3
- 0.4
- 0.5
- nightly
after_success:
- if [ $TRAVIS_JULIA_VERSION != "0.3" ]; 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
64 changes: 32 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,31 @@ Reasons to prefer `ArrayViews`:

## Main Features

- An efficient ``view`` function that implements array views
- An efficient ``aview`` function that implements array views
- Support of arrays of arbitrary dimension and arbitrary combinations of indexers
- Support view composition (*i.e.* construct views over views)
- Support ``aview`` composition (*i.e.* construct views over views)
- Special attention to ensure type stability in most cases
- Efficient indexing (both cartesian and linear)
- Light weight view construction
- Light weight array view construction
- A systematic approach to detect contiguous views (statically)
- Views work with linear algebra functions


## Overview

The key function in this package is ``view``:
The key function in this package is ``aview``. This function is similar to ``sub`` in Julia Base, except that it returns an aview instance with more efficient representation:

```julia
a = rand(4, 5, 6)

view(a, :)
view(a, :, 2)
view(a, 1:2, 1:2:5, 4)
view(a, 2, :, 3:6)
aview(a, :)
aview(a, :, 2)
aview(a, 1:2, 1:2:5, 4)
aview(a, 2, :, 3:6)
```

The ``view`` function returns a view of type ``ArrayView``. Here, ``ArrayView`` is an abstract type with two derived types (``ContiguousView`` and ``StridedView``), defined as:
The ``aview`` function returns an array view of type ``ArrayView``.
Here, ``ArrayView`` is an abstract type with two derived types (``ContiguousView`` and ``StridedView``), defined as:

```julia
abstract ArrayView{T,N,M} <: DenseArray{T,N}
Expand All @@ -95,7 +96,7 @@ The *contiguous rank* plays an important role in determining (statically) the co
* * * * * *
. . . . . .
```
Here, ``*`` indicates a position covered by the view, and ``.`` otherwise. We can see that the columns are not contiguous.
Here, ``*`` indicates a position covered by the array view, and ``.`` otherwise. We can see that the columns are not contiguous.

**2D View with contiguous rank 1**

Expand All @@ -107,7 +108,7 @@ Here, ``*`` indicates a position covered by the view, and ``.`` otherwise. We ca
. . . . . .
. . . . . .
```
We can see that each column is contiguous, while the entire view is not.
We can see that each column is contiguous, while the entire array view is not.


**2D View with contiguous rank 2**
Expand All @@ -120,15 +121,15 @@ We can see that each column is contiguous, while the entire view is not.
* * * * * *
* * * * * *
```
The entire 2D view is contiguous.
The entire 2D array view is contiguous.


Formally, when ``v`` is a view with contiguous rank ``M``, then ``view(v, :, :, ..., :, 1)`` must be contiguous when the number of colons is less than or equal to ``M``.
Formally, when ``v`` is an array view with contiguous rank ``M``, then ``aview(v, :, :, ..., :, 1)`` must be contiguous when the number of colons is less than or equal to ``M``.


#### View Types

The package provide a hierarchy of view types (defined as follows):
The package provide a hierarchy of array view types (defined as follows):

```julia
# T: the element type
Expand All @@ -151,42 +152,41 @@ Here, an instance of ``ArrayView`` maintains a reference to the underlying array

#### View Types in Action

The following example illustrates how contiguous rank is used to determine view types in practice.
The following example illustrates how contiguous rank is used to determine aview types in practice.

```julia
a = rand(m, n)

# safe views

v0 = view(a, :) # of type ContiguousView{Float64, 1}
v0 = aview(a, :) # of type ContiguousView{Float64, 1}

u1 = view(a, a:b, :) # of type StridedView{Float64, 2, 1}
u2 = view(u1, :, i) # of type ContiguousView{Float64, 1}
u1 = aview(a, a:b, :) # of type StridedView{Float64, 2, 1}
u2 = aview(u1, :, i) # of type ContiguousView{Float64, 1}

v1 = view(a, a:2:b, :) # of type StridedView{Float64, 2, 0}
v2 = view(v1, :, i) # of type StridedView{Float64, 1, 0}
v1 = aview(a, a:2:b, :) # of type StridedView{Float64, 2, 0}
v2 = aview(v1, :, i) # of type StridedView{Float64, 1, 0}

# unsafe views

v0 = unsafe_view(a, :) # of type UnsafeContiguousView{Float64, 1}
v0 = unsafe_aview(a, :) # of type UnsafeContiguousView{Float64, 1}

u1 = unsafe_view(a, a:b, :) # of type UnsafeStridedView{Float64, 2, 1}
u2 = unsafe_view(u1, :, i) # of type UnsafeContiguousView{Float64, 1}
u1 = unsafe_aview(a, a:b, :) # of type UnsafeStridedView{Float64, 2, 1}
u2 = unsafe_aview(u1, :, i) # of type UnsafeContiguousView{Float64, 1}

v1 = unsafe_view(a, a:2:b, :) # of type UnsafeStridedView{Float64, 2, 0}
v2 = unsafe_view(v1, :, i) # of type UnsafeStridedView{Float64, 1, 0}
v1 = unsafe_aview(a, a:2:b, :) # of type UnsafeStridedView{Float64, 2, 0}
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.*, ``:``).


## View Construction

The procedure of constructing a view consists of several steps:
The procedure of constructing a aview consists of several steps:

1. Compute the shape of a view. This is done by an internal function ``vshape``.
1. Compute the shape of an array view. This is done by an internal function ``vshape``.

2. Compute the offset of a view. This is done by an internal function ``aoffset``. The computation is based on the following formula:
2. Compute the offset of an array view. This is done by an internal function ``aoffset``. The computation is based on the following formula:

```
offset(v(I1, I2, ..., Im)) = (first(I1) - 1) * stride(v, 1)
Expand All @@ -197,7 +197,7 @@ The procedure of constructing a view consists of several steps:
3. Compute the contiguous rank, based on both view shape and the combination of indexer types. A type ``ContRank{M}`` is introduced for static computation of contiguous rank (please refer to ``src/contrank.jl`` for details).
4. Construct a view, where the view type is determined by both the number of dimensions and the value of contiguous rank (which is determined statically).
4. Construct a aview, where the array view type is determined by both the number of dimensions and the value of contiguous rank (which is determined statically).
For runtime efficiency, specialized methods of these functions are implemented for views of 1D, 2D, and 3D. These methods are extensively tested.
Expand All @@ -221,6 +221,6 @@ rowvec_view(a, i) # make a view of `a[i,:]` as a strided vector.
# `a` needs to be a matrix here (contiguous or strided)
ellipview(a, i) # make a view of the i-th slice of a
# e.g. `a` is a matrix => this is equiv. to `view(a, :, i)`
# `a` is a cube => this is equiv. to `view(a, :, :, i)`, etc.
# e.g. `a` is a matrix => this is equiv. to `aview(a, :, i)`
# `a` is a cube => this is equiv. to `aview(a, :, :, i)`, etc.
```
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
julia 0.3
julia 0.5
Compat
17 changes: 4 additions & 13 deletions src/ArrayViews.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION >= v"0.4.0-dev+6521" && __precompile__(true)
__precompile__(true)

module ArrayViews

Expand All @@ -7,16 +7,7 @@ using Compat
import Base: eltype, ndims, size, length, stride, strides
import Base: to_index, getindex, setindex!, parent, similar
import Base: Ptr, pointer

if VERSION >= v"0.4.0-dev+2085"
import Base: iscontiguous
end

if VERSION < v"0.4.0-dev+3768"
import Base: convert
else
import Base: unsafe_convert
end
import Base: iscontiguous, convert, unsafe_convert

export
StridedArrayView,
Expand All @@ -33,8 +24,8 @@ export

contiguous_view,
strided_view,
view,
unsafe_view,
aview,
unsafe_aview,
ellipview,
diagview,
rowvec_view,
Expand Down
4 changes: 2 additions & 2 deletions src/arrviews.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ ContiguousView(arr::Array, shp::Dims) = ContiguousView(arr, 0, shp)

immutable UnsafeContiguousView{T,N} <: UnsafeArrayView{T,N,N}
ptr::Ptr{T}
len::Int
shp::NTuple{N,Int}
len::Int
end

UnsafeContiguousView{T,N}(ptr::Ptr{T}, shp::NTuple{N,Int}) =
UnsafeContiguousView{T,N}(ptr, prod(shp), shp)
UnsafeContiguousView{T,N}(ptr, shp, prod(shp))

UnsafeContiguousView{T,N}(ptr::Ptr{T}, offset::Int, shp::NTuple{N,Int}) =
UnsafeContiguousView(ptr+offset*sizeof(T), shp)
Expand Down
14 changes: 7 additions & 7 deletions src/convenience.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# functions for convenience of use

## diagonal view
## diagonal aview

function diagview{T}(a::DenseArray{T,2})
m, n = size(a)
Expand All @@ -9,7 +9,7 @@ function diagview{T}(a::DenseArray{T,2})
StridedView(parent(a), offset(a), (len,), ContRank{0}, (s1 + s2,))
end

## row vector view
## row vector aview

function rowvec_view{T}(a::DenseArray{T,2}, i::Integer)
m, n = size(a)
Expand All @@ -32,8 +32,8 @@ end

## ellipview

@compat ellipview{T}(a::DenseArray{T,2}, i::Union{Integer, UnitRange}) = view(a, :, i)
@compat ellipview{T}(a::DenseArray{T,3}, i::Union{Integer, UnitRange}) = view(a, :, :, i)
@compat ellipview{T}(a::DenseArray{T,4}, i::Union{Integer, UnitRange}) = view(a, :, :, :, i)
@compat ellipview{T}(a::DenseArray{T,5}, i::Union{Integer, UnitRange}) = view(a, :, :, :, :, i)
@compat ellipview{T,N}(a::DenseArray{T,N}, i::Union{Integer, UnitRange}) = view(a, ntuple(i->Colon(),N-1)..., i)
@compat ellipview{T}(a::DenseArray{T,2}, i::Union{Integer, UnitRange}) = aview(a, :, i)
@compat ellipview{T}(a::DenseArray{T,3}, i::Union{Integer, UnitRange}) = aview(a, :, :, i)
@compat ellipview{T}(a::DenseArray{T,4}, i::Union{Integer, UnitRange}) = aview(a, :, :, :, i)
@compat ellipview{T}(a::DenseArray{T,5}, i::Union{Integer, UnitRange}) = aview(a, :, :, :, :, i)
@compat ellipview{T,N}(a::DenseArray{T,N}, i::Union{Integer, UnitRange}) = aview(a, ntuple(i->Colon(),N-1)..., i)
2 changes: 2 additions & 0 deletions src/deprecates.jl
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Base.@deprecate contiguous_view ContiguousView
Base.@deprecate strided_view StridedView
Base.@deprecate unsafe_aview unsafe_aview
Base.@deprecate view aview
Loading

0 comments on commit 2ed35eb

Please sign in to comment.