Skip to content

Commit

Permalink
initial setup of subview.jl
Browse files Browse the repository at this point in the history
  • Loading branch information
lindahua committed Jun 23, 2013
1 parent ff7d087 commit 4778e17
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions base/subview.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
## subviews of arrays ##

abstract AbstractStridedView{T,N} <: AbstractArray{T,N}
abstract AbstractContiguousView{T,N} <: AbstractStridedView{T,N}

typealias ContiguousArray{T,N} Union(Array{T,N}, AbstractContiguousView{T,N})

#####################################################################
#
# In general, a subview type should be a subtype
# of AbstractArray, and with following methods specialized:
#
# - isempty
# - length
# - size
# - getindex
# - setindex!
# - slice
#
# For subtypes of AbstractStridedView, we additionally have
#
# - stride
# - strides
# - pointer
#
# AbstractContiguousView is a subtype of AbstractStridedView,
# for which no additional methods are required. We just have
# to exploit the fact that the memory is contiguous.
#
# Notes:
# - getindex & setindex! do not do bound checking
# - We will check the validity of indexes upon the construction
# of a view using the ``sub`` function.
#
#####################################################################

## helpers

offset_pointer{T}(a::Ptr{T}, offset::Int) = a + sizeof(T) * offset


### Contiguous views ###

immutable VectorView{T,A<:AbstractArray} <: AbstractContiguousView{T,1}
parent::A
ptr::Ptr{T}
len::Int
end

isempty(a::VectorView) = (a.len == 0)
length(a::VectorView) = a.len
size(a::VectorView) = (a.len, 1)
size(a::VectorView, d::Int) = d == 1 ? a.len : 1
stride(a::VectorView, d::Int) = d == 1 ? 1 : throw(BoundsError())

This comment has been minimized.

Copy link
@timholy

timholy Jun 23, 2013

Member

For Julia's normal vectors:

julia> a = zeros(3)
3-element Float64 Array:
 0.0
 0.0
 0.0

julia> stride(a,1)
1

julia> stride(a,2)
3

julia> stride(a,3)
3

julia> stride(a,4)
3

This comment has been minimized.

Copy link
@timholy

timholy Jun 23, 2013

Member

Ah, I didn't realize it was inconsistent. I think the reality is that SubArray has gotten vastly less attention than Array, so when in doubt I would model off Array. In any event it is sensible to have stride(A, ndims(A)+1) return the number of elements in the array.

strides(a::VectorView) = (1,)

getindex(a::VectorView, i::Int) = unsafe_load(a.ptr, i)

This comment has been minimized.

Copy link
@timholy

timholy Jun 23, 2013

Member

We definitely need to have bounds-checking in place, even though I know it's bad for performance. Presumably the sticking point is #3030. I would put it in place, so that development with these types is "safe" and will be extra motivation for someone (perhaps one of us) to improve inlining.

This comment has been minimized.

Copy link
@timholy

timholy Jun 23, 2013

Member

Thinking about how one might get this working by inlining (something I have no experience with so am likely wrong), this may be a harder problem than #3030. I'd guess the sticking point is that you can't guarantee the output (it's not, say, one float or another; it's a float or an error). It may in fact be easier at the level of codegen. I imagine that we can get @JeffBezanson to chime in here about how best to do this, since I think this is a direction he's enthusiastic about.

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Jun 24, 2013

Member

It might make sense to add a boundscheck intrinsic, which would always be inlined and would also be disabled by the @inbounds macro.

This comment has been minimized.

Copy link
@lindahua

lindahua Jun 24, 2013

Author Contributor

Such an intrinsic would be of great help. Not only for this work but for so many things that may need bound checking.

setindex!(a::VectorView, v, i::Int) = unsafe_store!(a.ptr, v, i)

pointer(a::VectorView) = a.ptr
pointer(a::VectorView, i::Int) = offset_pointer(a.ptr, i-1)


### Strided views ###

immutable StridedVectorView{T,A<:AbstractArray} <: AbstractStridedView{T,1}
parent::A
ptr::Ptr{T}
len::Int
stride1::Int
end

isempty(a::StridedVectorView) = (a.len == 0)
length(a::StridedVectorView) = a.len
size(a::StridedVectorView) = (a.len, 1)
size(a::StridedVectorView, d::Int) = d == 1 ? a.len : 1
stride(a::StridedVectorView, d::Int) = d == 1 ? a.stride1 : throw(BoundsError())
strides(a::StridedVectorView) = (a.stride1,)

getindex(a::StridedVectorView, i::Int) = unsafe_load(a.ptr, (i-1) * a.stride1 + 1)
setindex!(a::StridedVectorView, v, i::Int) = unsafe_store!(a.ptr, v, (i-1) * a.stride1 + 1)

pointer(a::StridedVectorView) = a.ptr
pointer(a::StridedVectorView, i::Int) = offset_pointer(a.ptr, (i-1) * a.stride1)


1 comment on commit 4778e17

@lindahua
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Julia is inconsistent about this.

stride on the current version of SubArray raises bounds error when dim > ndims(a).

Please sign in to comment.